// http://jira.atlassian.com/s/617/1/3.0.2/_/download/batch/com.atlassian.gadgets.dashboard:dashboard/com.atlassian.gadgets.dashboard:dashboard.js
if (!this.JSON) {
    JSON = {}
}(function () {
    function f(n) {
        return n < 10 ? "0" + n : n
    }
    if (typeof Date.prototype.toJSON !== "function") {
        Date.prototype.toJSON = function (key) {
            return this.getUTCFullYear() + "-" + f(this.getUTCMonth() + 1) + "-" + f(this.getUTCDate()) + "T" + f(this.getUTCHours()) + ":" + f(this.getUTCMinutes()) + ":" + f(this.getUTCSeconds()) + "Z"
        };
        String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) {
            return this.valueOf()
        }
    }
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap, indent, meta = {
            "\b": "\\b",
            "\t": "\\t",
            "\n": "\\n",
            "\f": "\\f",
            "\r": "\\r",
            '"': '\\"',
            "\\": "\\\\"
        },
        rep;

    function quote(string) {
        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === "string" ? c : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4)
        }) + '"' : '"' + string + '"'
    }
    function str(key, holder) {
        var i, k, v, length, mind = gap,
            partial, value = holder[key];
        if (value && typeof value === "object" && typeof value.toJSON === "function") {
            value = value.toJSON(key)
        }
        if (typeof rep === "function") {
            value = rep.call(holder, key, value)
        }
        switch (typeof value) {
        case "string":
            return quote(value);
        case "number":
            return isFinite(value) ? String(value) : "null";
        case "boolean":
        case "null":
            return String(value);
        case "object":
            if (!value) {
                return "null"
            }
            gap += indent;
            partial = [];
            if (Object.prototype.toString.apply(value) === "[object Array]") {
                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || "null"
                }
                v = partial.length === 0 ? "[]" : gap ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" : "[" + partial.join(",") + "]";
                gap = mind;
                return v
            }
            if (rep && typeof rep === "object") {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    k = rep[i];
                    if (typeof k === "string") {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ": " : ":") + v)
                        }
                    }
                }
            } else {
                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ": " : ":") + v)
                        }
                    }
                }
            }
            v = partial.length === 0 ? "{}" : gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" : "{" + partial.join(",") + "}";
            gap = mind;
            return v
        }
    }
    if (typeof JSON.stringify !== "function") {
        JSON.stringify = function (value, replacer, space) {
            var i;
            gap = "";
            indent = "";
            if (typeof space === "number") {
                for (i = 0; i < space; i += 1) {
                    indent += " "
                }
            } else {
                if (typeof space === "string") {
                    indent = space
                }
            }
            rep = replacer;
            if (replacer && typeof replacer !== "function" && (typeof replacer !== "object" || typeof replacer.length !== "number")) {
                throw new Error("JSON.stringify")
            }
            return str("", {
                "": value
            })
        }
    }
    if (typeof JSON.parse !== "function") {
        JSON.parse = function (text, reviver) {
            var j;

            function walk(holder, key) {
                var k, v, value = holder[key];
                if (value && typeof value === "object") {
                    for (k in value) {
                        if (Object.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v
                            } else {
                                delete value[k]
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value)
            }
            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4)
                })
            }
            if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]").replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) {
                j = eval("(" + text + ")");
                return typeof reviver === "function" ? walk({
                    "": j
                }, "") : j
            }
            throw new SyntaxError("JSON.parse")
        }
    }
})();
jQuery.effects || (function ($) {
    $.effects = {};
    $.each(["backgroundColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "outlineColor"], function (i, attr) {
        $.fx.step[attr] = function (fx) {
            if (!fx.colorInit) {
                fx.start = getColor(fx.elem, attr);
                fx.end = getRGB(fx.end);
                fx.colorInit = true
            }
            fx.elem.style[attr] = "rgb(" + Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + "," + Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + "," + Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ")"
        }
    });

    function getRGB(color) {
        var result;
        if (color && color.constructor == Array && color.length == 3) {
            return color
        }
        if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) {
            return [parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10)]
        }
        if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) {
            return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55, parseFloat(result[3]) * 2.55]
        }
        if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) {
            return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]
        }
        if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) {
            return [parseInt(result[1] + result[1], 16), parseInt(result[2] + result[2], 16), parseInt(result[3] + result[3], 16)]
        }
        if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) {
            return colors["transparent"]
        }
        return colors[$.trim(color).toLowerCase()]
    }
    function getColor(elem, attr) {
        var color;
        do {
            color = $.curCSS(elem, attr);
            if (color != "" && color != "transparent" || $.nodeName(elem, "body")) {
                break
            }
            attr = "backgroundColor"
        } while (elem = elem.parentNode);
        return getRGB(color)
    }
    var colors = {
        aqua: [0, 255, 255],
        azure: [240, 255, 255],
        beige: [245, 245, 220],
        black: [0, 0, 0],
        blue: [0, 0, 255],
        brown: [165, 42, 42],
        cyan: [0, 255, 255],
        darkblue: [0, 0, 139],
        darkcyan: [0, 139, 139],
        darkgrey: [169, 169, 169],
        darkgreen: [0, 100, 0],
        darkkhaki: [189, 183, 107],
        darkmagenta: [139, 0, 139],
        darkolivegreen: [85, 107, 47],
        darkorange: [255, 140, 0],
        darkorchid: [153, 50, 204],
        darkred: [139, 0, 0],
        darksalmon: [233, 150, 122],
        darkviolet: [148, 0, 211],
        fuchsia: [255, 0, 255],
        gold: [255, 215, 0],
        green: [0, 128, 0],
        indigo: [75, 0, 130],
        khaki: [240, 230, 140],
        lightblue: [173, 216, 230],
        lightcyan: [224, 255, 255],
        lightgreen: [144, 238, 144],
        lightgrey: [211, 211, 211],
        lightpink: [255, 182, 193],
        lightyellow: [255, 255, 224],
        lime: [0, 255, 0],
        magenta: [255, 0, 255],
        maroon: [128, 0, 0],
        navy: [0, 0, 128],
        olive: [128, 128, 0],
        orange: [255, 165, 0],
        pink: [255, 192, 203],
        purple: [128, 0, 128],
        violet: [128, 0, 128],
        red: [255, 0, 0],
        silver: [192, 192, 192],
        white: [255, 255, 255],
        yellow: [255, 255, 0],
        transparent: [255, 255, 255]
    };
    var classAnimationActions = ["add", "remove", "toggle"],
        shorthandStyles = {
            border: 1,
            borderBottom: 1,
            borderColor: 1,
            borderLeft: 1,
            borderRight: 1,
            borderTop: 1,
            borderWidth: 1,
            margin: 1,
            padding: 1
        };

    function getElementStyles() {
        var style = document.defaultView ? document.defaultView.getComputedStyle(this, null) : this.currentStyle,
            newStyle = {},
            key, camelCase;
        if (style && style.length && style[0] && style[style[0]]) {
            var len = style.length;
            while (len--) {
                key = style[len];
                if (typeof style[key] == "string") {
                    camelCase = key.replace(/\-(\w)/g, function (all, letter) {
                        return letter.toUpperCase()
                    });
                    newStyle[camelCase] = style[key]
                }
            }
        } else {
            for (key in style) {
                if (typeof style[key] === "string") {
                    newStyle[key] = style[key]
                }
            }
        }
        return newStyle
    }
    function filterStyles(styles) {
        var name, value;
        for (name in styles) {
            value = styles[name];
            if (value == null || $.isFunction(value) || name in shorthandStyles || (/scrollbar/).test(name) || (!(/color/i).test(name) && isNaN(parseFloat(value)))) {
                delete styles[name]
            }
        }
        return styles
    }
    function styleDifference(oldStyle, newStyle) {
        var diff = {
            _: 0
        },
            name;
        for (name in newStyle) {
            if (oldStyle[name] != newStyle[name]) {
                diff[name] = newStyle[name]
            }
        }
        return diff
    }
    $.effects.animateClass = function (value, duration, easing, callback) {
        if ($.isFunction(easing)) {
            callback = easing;
            easing = null
        }
        return this.each(function () {
            var that = $(this),
                originalStyleAttr = that.attr("style") || " ",
                originalStyle = filterStyles(getElementStyles.call(this)),
                newStyle, className = that.attr("className");
            $.each(classAnimationActions, function (i, action) {
                if (value[action]) {
                    that[action + "Class"](value[action])
                }
            });
            newStyle = filterStyles(getElementStyles.call(this));
            that.attr("className", className);
            that.animate(styleDifference(originalStyle, newStyle), duration, easing, function () {
                $.each(classAnimationActions, function (i, action) {
                    if (value[action]) {
                        that[action + "Class"](value[action])
                    }
                });
                if (typeof that.attr("style") == "object") {
                    that.attr("style").cssText = "";
                    that.attr("style").cssText = originalStyleAttr
                } else {
                    that.attr("style", originalStyleAttr)
                }
                if (callback) {
                    callback.apply(this, arguments)
                }
            })
        })
    };
    $.fn.extend({
        _addClass: $.fn.addClass,
        addClass: function (classNames, speed, easing, callback) {
            return speed ? $.effects.animateClass.apply(this, [{
                add: classNames
            },
            speed, easing, callback]) : this._addClass(classNames)
        },
        _removeClass: $.fn.removeClass,
        removeClass: function (classNames, speed, easing, callback) {
            return speed ? $.effects.animateClass.apply(this, [{
                remove: classNames
            },
            speed, easing, callback]) : this._removeClass(classNames)
        },
        _toggleClass: $.fn.toggleClass,
        toggleClass: function (classNames, force, speed, easing, callback) {
            if (typeof force == "boolean" || force === undefined) {
                if (!speed) {
                    return this._toggleClass(classNames, force)
                } else {
                    return $.effects.animateClass.apply(this, [(force ? {
                        add: classNames
                    } : {
                        remove: classNames
                    }), speed, easing, callback])
                }
            } else {
                return $.effects.animateClass.apply(this, [{
                    toggle: classNames
                },
                force, speed, easing])
            }
        },
        switchClass: function (remove, add, speed, easing, callback) {
            return $.effects.animateClass.apply(this, [{
                add: add,
                remove: remove
            },
            speed, easing, callback])
        }
    });
    $.extend($.effects, {
        version: "1.8rc3",
        save: function (element, set) {
            for (var i = 0; i < set.length; i++) {
                if (set[i] !== null) {
                    element.data("ec.storage." + set[i], element[0].style[set[i]])
                }
            }
        },
        restore: function (element, set) {
            for (var i = 0; i < set.length; i++) {
                if (set[i] !== null) {
                    element.css(set[i], element.data("ec.storage." + set[i]))
                }
            }
        },
        setMode: function (el, mode) {
            if (mode == "toggle") {
                mode = el.is(":hidden") ? "show" : "hide"
            }
            return mode
        },
        getBaseline: function (origin, original) {
            var y, x;
            switch (origin[0]) {
            case "top":
                y = 0;
                break;
            case "middle":
                y = 0.5;
                break;
            case "bottom":
                y = 1;
                break;
            default:
                y = origin[0] / original.height
            }
            switch (origin[1]) {
            case "left":
                x = 0;
                break;
            case "center":
                x = 0.5;
                break;
            case "right":
                x = 1;
                break;
            default:
                x = origin[1] / original.width
            }
            return {
                x: x,
                y: y
            }
        },
        createWrapper: function (element) {
            if (element.parent().is(".ui-effects-wrapper")) {
                return element.parent()
            }
            var props = {
                width: element.outerWidth(true),
                height: element.outerHeight(true),
                "float": element.css("float")
            },
                wrapper = $("<div></div>").addClass("ui-effects-wrapper").css({
                    fontSize: "100%",
                    background: "transparent",
                    border: "none",
                    margin: 0,
                    padding: 0
                });
            element.wrap(wrapper);
            wrapper = element.parent();
            if (element.css("position") == "static") {
                wrapper.css({
                    position: "relative"
                });
                element.css({
                    position: "relative"
                })
            } else {
                $.extend(props, {
                    position: element.css("position"),
                    zIndex: element.css("z-index")
                });
                $.each(["top", "left", "bottom", "right"], function (i, pos) {
                    props[pos] = element.css(pos);
                    if (isNaN(parseInt(props[pos], 10))) {
                        props[pos] = "auto"
                    }
                });
                element.css({
                    position: "relative",
                    top: 0,
                    left: 0
                })
            }
            return wrapper.css(props).show()
        },
        removeWrapper: function (element) {
            if (element.parent().is(".ui-effects-wrapper")) {
                return element.parent().replaceWith(element)
            }
            return element
        },
        setTransition: function (element, list, factor, value) {
            value = value || {};
            $.each(list, function (i, x) {
                unit = element.cssUnit(x);
                if (unit[0] > 0) {
                    value[x] = unit[0] * factor + unit[1]
                }
            });
            return value
        }
    });

    function _normalizeArguments(effect, options, speed, callback) {
        if (typeof effect == "object") {
            callback = options;
            speed = null;
            options = effect;
            effect = options.effect
        }
        if ($.isFunction(options)) {
            callback = options;
            speed = null;
            options = {}
        }
        if (typeof options == "number" || $.fx.speeds[options]) {
            callback = speed;
            speed = options;
            options = {}
        }
        options = options || {};
        speed = speed || options.duration;
        speed = $.fx.off ? 0 : typeof speed == "number" ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
        callback = callback || options.complete;
        return [effect, options, speed, callback]
    }
    $.fn.extend({
        effect: function (effect, options, speed, callback) {
            var args = _normalizeArguments.apply(this, arguments),
                args2 = {
                    options: args[1],
                    duration: args[2],
                    callback: args[3]
                },
                effectMethod = $.effects[effect];
            return effectMethod && !$.fx.off ? effectMethod.call(this, args2) : this
        },
        _show: $.fn.show,
        show: function (speed) {
            if (!speed || typeof speed == "number" || $.fx.speeds[speed]) {
                return this._show.apply(this, arguments)
            } else {
                var args = _normalizeArguments.apply(this, arguments);
                args[1].mode = "show";
                return this.effect.apply(this, args)
            }
        },
        _hide: $.fn.hide,
        hide: function (speed) {
            if (!speed || typeof speed == "number" || $.fx.speeds[speed]) {
                return this._hide.apply(this, arguments)
            } else {
                var args = _normalizeArguments.apply(this, arguments);
                args[1].mode = "hide";
                return this.effect.apply(this, args)
            }
        },
        __toggle: $.fn.toggle,
        toggle: function (speed) {
            if (!speed || typeof speed == "number" || $.fx.speeds[speed] || typeof speed == "boolean" || $.isFunction(speed)) {
                return this.__toggle.apply(this, arguments)
            } else {
                var args = _normalizeArguments.apply(this, arguments);
                args[1].mode = "toggle";
                return this.effect.apply(this, args)
            }
        },
        cssUnit: function (key) {
            var style = this.css(key),
                val = [];
            $.each(["em", "px", "%", "pt"], function (i, unit) {
                if (style.indexOf(unit) > 0) {
                    val = [parseFloat(style), unit]
                }
            });
            return val
        }
    });
    $.easing.jswing = $.easing.swing;
    $.extend($.easing, {
        def: "easeOutQuad",
        swing: function (x, t, b, c, d) {
            return $.easing[$.easing.def](x, t, b, c, d)
        },
        easeInQuad: function (x, t, b, c, d) {
            return c * (t /= d) * t + b
        },
        easeOutQuad: function (x, t, b, c, d) {
            return -c * (t /= d) * (t - 2) + b
        },
        easeInOutQuad: function (x, t, b, c, d) {
            if ((t /= d / 2) < 1) {
                return c / 2 * t * t + b
            }
            return -c / 2 * ((--t) * (t - 2) - 1) + b
        },
        easeInCubic: function (x, t, b, c, d) {
            return c * (t /= d) * t * t + b
        },
        easeOutCubic: function (x, t, b, c, d) {
            return c * ((t = t / d - 1) * t * t + 1) + b
        },
        easeInOutCubic: function (x, t, b, c, d) {
            if ((t /= d / 2) < 1) {
                return c / 2 * t * t * t + b
            }
            return c / 2 * ((t -= 2) * t * t + 2) + b
        },
        easeInQuart: function (x, t, b, c, d) {
            return c * (t /= d) * t * t * t + b
        },
        easeOutQuart: function (x, t, b, c, d) {
            return -c * ((t = t / d - 1) * t * t * t - 1) + b
        },
        easeInOutQuart: function (x, t, b, c, d) {
            if ((t /= d / 2) < 1) {
                return c / 2 * t * t * t * t + b
            }
            return -c / 2 * ((t -= 2) * t * t * t - 2) + b
        },
        easeInQuint: function (x, t, b, c, d) {
            return c * (t /= d) * t * t * t * t + b
        },
        easeOutQuint: function (x, t, b, c, d) {
            return c * ((t = t / d - 1) * t * t * t * t + 1) + b
        },
        easeInOutQuint: function (x, t, b, c, d) {
            if ((t /= d / 2) < 1) {
                return c / 2 * t * t * t * t * t + b
            }
            return c / 2 * ((t -= 2) * t * t * t * t + 2) + b
        },
        easeInSine: function (x, t, b, c, d) {
            return -c * Math.cos(t / d * (Math.PI / 2)) + c + b
        },
        easeOutSine: function (x, t, b, c, d) {
            return c * Math.sin(t / d * (Math.PI / 2)) + b
        },
        easeInOutSine: function (x, t, b, c, d) {
            return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b
        },
        easeInExpo: function (x, t, b, c, d) {
            return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b
        },
        easeOutExpo: function (x, t, b, c, d) {
            return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b
        },
        easeInOutExpo: function (x, t, b, c, d) {
            if (t == 0) {
                return b
            }
            if (t == d) {
                return b + c
            }
            if ((t /= d / 2) < 1) {
                return c / 2 * Math.pow(2, 10 * (t - 1)) + b
            }
            return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b
        },
        easeInCirc: function (x, t, b, c, d) {
            return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b
        },
        easeOutCirc: function (x, t, b, c, d) {
            return c * Math.sqrt(1 - (t = t / d - 1) * t) + b
        },
        easeInOutCirc: function (x, t, b, c, d) {
            if ((t /= d / 2) < 1) {
                return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b
            }
            return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b
        },
        easeInElastic: function (x, t, b, c, d) {
            var s = 1.70158;
            var p = 0;
            var a = c;
            if (t == 0) {
                return b
            }
            if ((t /= d) == 1) {
                return b + c
            }
            if (!p) {
                p = d * 0.3
            }
            if (a < Math.abs(c)) {
                a = c;
                var s = p / 4
            } else {
                var s = p / (2 * Math.PI) * Math.asin(c / a)
            }
            return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b
        },
        easeOutElastic: function (x, t, b, c, d) {
            var s = 1.70158;
            var p = 0;
            var a = c;
            if (t == 0) {
                return b
            }
            if ((t /= d) == 1) {
                return b + c
            }
            if (!p) {
                p = d * 0.3
            }
            if (a < Math.abs(c)) {
                a = c;
                var s = p / 4
            } else {
                var s = p / (2 * Math.PI) * Math.asin(c / a)
            }
            return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b
        },
        easeInOutElastic: function (x, t, b, c, d) {
            var s = 1.70158;
            var p = 0;
            var a = c;
            if (t == 0) {
                return b
            }
            if ((t /= d / 2) == 2) {
                return b + c
            }
            if (!p) {
                p = d * (0.3 * 1.5)
            }
            if (a < Math.abs(c)) {
                a = c;
                var s = p / 4
            } else {
                var s = p / (2 * Math.PI) * Math.asin(c / a)
            }
            if (t < 1) {
                return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b
            }
            return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b
        },
        easeInBack: function (x, t, b, c, d, s) {
            if (s == undefined) {
                s = 1.70158
            }
            return c * (t /= d) * t * ((s + 1) * t - s) + b
        },
        easeOutBack: function (x, t, b, c, d, s) {
            if (s == undefined) {
                s = 1.70158
            }
            return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b
        },
        easeInOutBack: function (x, t, b, c, d, s) {
            if (s == undefined) {
                s = 1.70158
            }
            if ((t /= d / 2) < 1) {
                return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b
            }
            return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b
        },
        easeInBounce: function (x, t, b, c, d) {
            return c - $.easing.easeOutBounce(x, d - t, 0, c, d) + b
        },
        easeOutBounce: function (x, t, b, c, d) {
            if ((t /= d) < (1 / 2.75)) {
                return c * (7.5625 * t * t) + b
            } else {
                if (t < (2 / 2.75)) {
                    return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b
                } else {
                    if (t < (2.5 / 2.75)) {
                        return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b
                    } else {
                        return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b
                    }
                }
            }
        },
        easeInOutBounce: function (x, t, b, c, d) {
            if (t < d / 2) {
                return $.easing.easeInBounce(x, t * 2, 0, c, d) * 0.5 + b
            }
            return $.easing.easeOutBounce(x, t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b
        }
    })
})(jQuery);
AJS.clone = function (o) {
    function F() {}
    F.prototype = o;
    return new F()
};
if (!console.error) {
    console.log = console.warn = console.error = console.time = console.timeEnd = function () {}
}
AJS.parseUri = function (uri, strict) {
    var unesc = window.decodeURIComponent || unescape;
    var esc = window.encodeURIComponent || escape;

    function parseUri(str) {
        var o = parseUri.options,
            m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
            uri = {},
            i = 14;
        while (i--) {
            uri[o.key[i]] = m[i] || ""
        }
        uri[o.q.name] = {};
        uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
            if ($1) {
                uri[o.q.name][unesc($1)] = unesc($2)
            }
        });
        return uri
    }
    parseUri.options = {
        strictMode: !! strict,
        key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"],
        q: {
            name: "queryKey",
            parser: /(?:^|&)([^&=]*)=?([^&]*)/g
        },
        parser: {
            strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
            loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
        }
    };
    uri = parseUri(uri);
    uri.toString = function () {
        var params = [];
        AJS.$.each(uri.queryKey, function (name, value) {
            params.push(esc(name) + "=" + esc(value))
        });
        return uri.protocol + "://" + uri.authority + uri.path + "?" + params.join("&") + "#" + uri.anchor
    };
    return uri
};
var ZParse = function (implementation) {
        this.implementation = implementation;
        this.header = ["var $text = [];", "var _write = function(text) {", '$text.push((typeof text == "number")?text:(text||""));', "};", "var top = $data;", "with($data){ "].join("");
        this.footer = '}return $text.join("");';
        this.escapeChars = ["\\", "'", '"', ["\n", "\\n"],
            ["\t", "\\t"],
            ["\r", "\\r"]
        ]
    };
ZParse.implementation = {};
ZParse.prototype.parse = function (source) {
    this.sourceArray = ZParse.parseToArray(source, this.implementation);
    this.sourceTree = ZParse.parseToTree(this.sourceArray.all, this.implementation);
    this.functionText = ZParse.parseToScript(this.sourceTree, this.escapeChars, this.implementation, this);
    try {
        this.functionScript = new Function("$data", this.header + this.functionText + this.footer);
        return true
    } catch (e) {
        this.error = e;
        return false
    }
};
ZParse.clean = function (str) {
    return str.replace(/[\n\r\t](?!.*?<)/gmi, "").replace(/(<\w+?|\"+?)\s{2,}/g, "$1 ")
};
ZParse.prototype.process = function (data, bind) {
    if (bind) {
        return ZParse.clean(this.functionScript.apply(bind, [data]))
    } else {
        return ZParse.clean(this.functionScript(data))
    }
};
ZParse.escape = function (source, list) {
    for (var i = 0; i < list.length; i++) {
        if (list[i] instanceof Array) {
            source = source.replace(new RegExp(list[i][0], "gi"), list[i][1])
        } else {
            source = source.replace(new RegExp("\\" + list[i], "gi"), "\\" + list[i])
        }
    }
    return source
};
ZParse.parseToArray = function (source, imp) {
    var opener, closer, delimiter;
    var text = [],
        tags = [],
        all = [];
    while (source) {
        for (var i in imp) {
            if (!delimiter || source.indexOf(imp[delimiter].opener) == -1) {
                delimiter = i
            }
            if (source.indexOf(imp[i].opener) != -1) {
                if (source.indexOf(imp[delimiter].opener) > source.indexOf(imp[i].opener)) {
                    delimiter = i
                }
            }
        }
        opener = source.indexOf(imp[delimiter].opener);
        closer = source.indexOf(imp[delimiter].closer) + imp[delimiter].closer.length;
        if (opener != -1) {
            text.push(source.substring(0, opener));
            tags.push(source.substring(opener, closer));
            source = source.substring(closer)
        } else {
            text.push(source);
            source = ""
        }
    }
    for (var i = 0; i < text.length; i++) {
        all.push(text[i]);
        if (tags[i]) {
            all.push(tags[i])
        }
    }
    return {
        text: text,
        tags: tags,
        all: all
    }
};
ZParse.parseArguments = function (source, expr) {
    var args = ZParse.parseToArray(expr, {
        expr: {
            opener: "{",
            closer: "}"
        }
    }).tags;
    expr = ZParse.escape(expr, ["(", ")", "[", "]", ",", ".", "<", ">", "*", "$", "@"]);
    for (var i = 0; i < args.length; i++) {
        expr = expr.replace(args[i], "(.*)");
        args[i] = args[i].replace("{", "").replace("}", "")
    }
    var matches = source.match(new RegExp(expr));
    var result = {};
    if (matches) {
        for (var i = 0; i < args.length; i++) {
            result[args[i]] = matches[i + 1]
        }
    }
    return result
};
ZParse.parseTag = function (source, imp) {
    var delimiter;
    for (var i in imp) {
        if (source.indexOf(imp[i].opener) == 0) {
            delimiter = i;
            break
        }
    }
    if (!delimiter) {
        return false
    }
    source = source.substring(imp[delimiter].opener.length, source.indexOf(imp[delimiter].closer));
    var tagname = "";
    var closer = "";
    if (imp[delimiter].tags) {
        var tagArray = [];
        for (var i in imp[delimiter].tags) {
            tagArray.push(i)
        }
        var regex = new RegExp("^(/){0,1}(" + tagArray.join("|") + ")\\s*(.*)");
        var res = source.match(regex);
        if (!res) {
            return false
        }
        closer = res[1] ? true : false;
        tagname = res[2];
        source = res[3]
    }
    if (tagname) {
        if (imp[delimiter].tags[tagname].type == "single" && closer) {
            return false
        }
        if (imp[delimiter].tags[tagname].type == "block" && closer) {
            return {
                delimiter: delimiter,
                tagname: tagname,
                closer: true
            }
        }
    }
    var args = {};
    if (tagname && imp[delimiter].tags[tagname].arguments) {
        args = ZParse.parseArguments(source, imp[delimiter].tags[tagname].arguments)
    } else {
        if (!tagname && imp[delimiter].arguments) {
            args = ZParse.parseArguments(source, imp[delimiter].arguments)
        }
    }
    return {
        delimiter: delimiter,
        tagname: tagname,
        source: source,
        arguments: args
    }
};
ZParse.parseToTree = function (array, imp) {
    var obj, res, current, nr = 0;
    var doc = {
        isDocument: true,
        innerSource: array.join(""),
        children: []
    };
    var addChild = function (parent, child) {
            child.nr = parent.children.length;
            parent.children.push(child)
        };
    current = doc;
    for (var i = 0; i < array.length; i++) {
        res = ZParse.parseTag(array[i], imp);
        if (!res) {
            if (array[i]) {
                array[i].parent = current;
                addChild(current, array[i])
            }
        } else {
            obj = {};
            obj.i = i;
            obj.tagname = res.tagname;
            obj.delimiter = res.delimiter;
            obj.arguments = res.arguments;
            obj.argSource = res.source;
            obj.parent = current;
            if (res.tagname && imp[res.delimiter].tags[res.tagname].noTextBefore && !res.closer && typeof current.children[current.children.length - 1] == "string") {
                current.children.pop()
            }
            if (res.tagname && imp[res.delimiter].tags[res.tagname].type == "block") {
                if (!res.closer) {
                    addChild(current, obj);
                    current = obj;
                    current.children = []
                } else {
                    if (current.tagname == res.tagname) {
                        current.innerSource = "";
                        for (var j = current.i + 1; j < i; j++) {
                            current.innerSource += array[j]
                        }
                        current = current.parent
                    }
                }
            } else {
                addChild(current, obj)
            }
        }
    }
    return doc
};
ZParse.parseToScript = function (tree, escape, imp, caller) {
    if (typeof tree == "string") {
        return "_write('" + ZParse.escape(tree, escape) + "');"
    }
    var result, content = [];
    if (tree.children) {
        for (var i = 0; i < tree.children.length; i++) {
            content.push(ZParse.parseToScript(tree.children[i], escape, imp, caller))
        }
    }
    if (!tree.isDocument) {
        if (tree.tagname) {
            return imp[tree.delimiter].tags[tree.tagname].handler(tree, content.join(""), caller)
        } else {
            return imp[tree.delimiter].handler(tree, content.join(""), caller)
        }
    } else {
        return content.join("")
    }
};
ZParse.parseXMLToJSON = function (xml) {
    var result;
    if (xml.childNodes && xml.childNodes.length == 1 && xml.childNodes[0].nodeName == "#text") {
        result = xml.childNodes[0].nodeValue
    } else {
        result = {};
        for (var i = 0; i < xml.childNodes.length; i++) {
            if (result[xml.childNodes[i].nodeName]) {
                if (!(result[xml.childNodes[i].nodeName] instanceof Array)) {
                    result[xml.childNodes[i].nodeName] = [result[xml.childNodes[i].nodeName]]
                }
                result[xml.childNodes[i].nodeName].push(ZParse.parseXMLToJSON(xml.childNodes[i]))
            } else {
                if (xml.childNodes[i].nodeName.indexOf("#") == -1) {
                    result[xml.childNodes[i].nodeName] = ZParse.parseXMLToJSON(xml.childNodes[i])
                }
            }
        }
    }
    if (xml.attributes) {
        for (var i = 0; i < xml.attributes.length; i++) {
            result["@" + xml.attributes[i].nodeName] = xml.attributes[i].nodeValue
        }
    }
    return result
};
var Implementation = {
    statement: {
        opener: "<?",
        closer: "?>",
        tags: {
            "foreach": {
                arguments: "{element} in {object}",
                type: "block",
                handler: function (tree, content, caller) {
                    var element = tree.arguments.element;
                    var object = tree.arguments.object;
                    var cond = (tree.parent.children[tree.nr + 1] && tree.parent.children[tree.nr + 1].tagname == "else");
                    var iff = ["if( (", object, " instanceof Array && ", object, ".length > 0) || ", "(!(", object, " instanceof Array) && ", object, ") ) {"].join("");
                    return [cond ? iff : "", "var ", element, ";", "if(", object, " instanceof Array) {", "for(var ", element, "_index=0; ", element, "_index<", object, ".length; ", element, "_index++) {", element, " = ", object, "[", element, "_index];", content, "}", "} else {", "for (var ", element, "_index in ", object, ") {", element, " = ", object, "[", element, "_index];", content, "}", "}", cond ? "}" : ""].join("")
                }
            },
            "for": {
                arguments: "{element} in {object}",
                type: "block",
                handler: function (tree, content, caller) {
                    var element = tree.arguments.element;
                    var object = tree.arguments.object;
                    var cond = (tree.parent.children[tree.nr + 1] && tree.parent.children[tree.nr + 1].tagname == "else");
                    var iff = ["if( (", object, " instanceof Array && ", object, ".length > 0) || ", "(!(", object, " instanceof Array) && ", object, ") ) {"].join("");
                    return [cond ? iff : "", "if(", object, " instanceof Array) {", "for(var ", element, "=0; ", element, "<", object, ".length; ", element, "++) {", content, "}", "} else {", "for(var ", element, " in ", object, ") {", content, "}", "}", cond ? "}" : ""].join("")
                }
            },
            "if": {
                type: "block",
                handler: function (tree, content, caller) {
                    var condition = tree.argSource;
                    return ["if(", condition, ") {", content, "}"].join("")
                }
            },
            "elseif": {
                type: "block",
                noTextBefore: true,
                handler: function (tree, content, caller) {
                    var condition = tree.argSource;
                    return ["else if(", condition, ") {", content, "}"].join("")
                }
            },
            "else": {
                type: "block",
                noTextBefore: true,
                handler: function (tree, content, caller) {
                    return ["else {", content, "}"].join("")
                }
            },
            "macro": {
                arguments: "{name}({args})",
                type: "block",
                handler: function (tree, content, caller) {
                    var name = tree.arguments.name;
                    var args = tree.arguments.args;
                    var point = (name.indexOf(".") > 0);
                    return [point ? "" : "var ", name, " = function(", args, ") {", "var top = " + args + ";", "with (" + args + ") {", "var $text = [];", "var _write = function(text) {", '$text.push((typeof text == "number")?text:(text||""));', "};", content, "}", 'return $text.join("");', "};"].join("")
                }
            },
            "cdata": {
                type: "block",
                handler: function (tree, content, caller) {
                    return "_write('" + ZParse.escape(tree.innerSource, caller.escapeChars) + "');"
                }
            }
        }
    },
    print: {
        opener: "${",
        closer: "}",
        handler: function (tree, content, caller) {
            return "_write(" + tree.argSource + ");"
        }
    },
    alternatePrint: {
        opener: "<$",
        closer: ":>",
        handler: function (tree, content, caller) {
            return "_write(" + tree.argSource + ");"
        }
    },
    script: {
        opener: "<%",
        closer: "%>",
        handler: function (tree, content, caller) {
            return tree.argSource
        }
    }
};
AJS.debug = false;
AG = {};
AG.DashboardManager = (function () {
    var dashboard, layouts = [],
        createMenu = function (json) {
            var editButton, descriptor;
            descriptor = AG.render.getDescriptor("dashboardMenu", json);
            dashboard.contents.append(AG.render(descriptor));
            editButton = AJS.$("#layout-changer");
            editButton.click(function (e) {
                e.preventDefault();
                AG.DashboardManager.editLayout()
            });
            AJS.$("#dashboard-tools-dropdown").dropDown("standard", {
                trigger: ".aui-dd-link"
            })
        };
    return {
        getDashboard: function () {
            return dashboard
        },
        addLayout: function (descriptor) {
            var layout = AG.LayoutManager(descriptor);
            layouts.push(layout);
            if (descriptor.active !== false) {
                this.setLayout(layout)
            }
            layout.init()
        },
        showShims: function () {
            if (!AJS.$("body").hasClass("propagation-blocker")) {
                AJS.$("body").addClass("propagation-blocker");
                this.getDashboard().shim.height(this.getDashboard().outerHeight())
            }
        },
        hideShims: function () {
            if (AJS.$("body").hasClass("propagation-blocker")) {
                AJS.$("body").removeClass("propagation-blocker")
            }
        },
        doDiagnostics: function () {
            AJS.$.ajax({
                type: "post",
                url: AG.param.get("dashboardDiagnosticsUrl"),
                data: {
                    uri: document.location.href
                },
                error: function (request) {
                    if (request.status == 500) {
                        diagnosticsErrorDisplay(request)
                    }
                },
                success: function (data) {
                    AJS.$("#diagnostic-warning").addClass("hidden")
                }
            });
            var diagnosticsErrorDisplay = function (request) {
                    var diagnosticsWarningDiv = AJS.$("#diagnostic-warning");
                    diagnosticsWarningDiv.html(request.responseText);
                    var learnMoreText = "Click here to learn more";
                    var diagnosticsContentDiv = AJS.$("#diagnostic-content", diagnosticsWarningDiv);
                    var learnMoreLink = AJS.$("#learn-more-link", diagnosticsWarningDiv);
                    var displayErrorLink = AJS.$("#display-error-link", diagnosticsWarningDiv);
                    var stackTraceDiv = AJS.$("#error-stack-trace", diagnosticsWarningDiv);
                    var closeWarning = function () {
                            diagnosticsWarningDiv.slideUp();
                            diagnosticsWarningDiv.addClass("hidden");
                            AJS.$.ajax({
                                type: "post",
                                url: AG.param.get("dashboardDiagnosticsUrl"),
                                data: {
                                    method: "delete"
                                }
                            })
                        };
                    var setToggleDetails = function (link, detailDiv) {
                            link.click(function () {
                                if (link.text() == "Hide") {
                                    link.text(learnMoreText);
                                    detailDiv.slideUp();
                                    detailDiv.addClass("hidden")
                                } else {
                                    detailDiv.removeClass("hidden");
                                    detailDiv.slideDown("slow");
                                    link.text("Hide")
                                }
                            })
                        };
                    setToggleDetails(learnMoreLink, diagnosticsContentDiv);
                    setToggleDetails(displayErrorLink, stackTraceDiv);
                    AJS.$("#diagnostic-warning .close").click(function () {
                        closeWarning()
                    });
                    diagnosticsWarningDiv.removeClass("hidden")
                }
        },
        editLayout: function () {
            var descriptor, popup;
            descriptor = AG.render.getDescriptor("layoutDialog", {
                layoutType: AG.DashboardManager.getLayout().getLayout()
            });
            popup = AJS.popup(507, 150, "layout-dialog");
            popup.element.html(AG.render(descriptor)).addClass(AG.LayoutManager.getLayoutAttrName(descriptor.layoutType)).addClass("aui-dialog");
            AJS.$("#" + descriptor.closeId, popup.element).click(function (e) {
                popup.hide();
                e.preventDefault()
            });
            AJS.$.each(AG.LayoutManager.layouts, function () {
                var layout = this,
                    layoutAttrName = AG.LayoutManager.getLayoutAttrName(layout);
                AJS.$("#" + layoutAttrName).click(function (e) {
                    var activeLayout = AG.DashboardManager.getLayout();
                    popup.element.removeClass(AG.LayoutManager.getLayoutAttrName(activeLayout.getLayout())).addClass(layoutAttrName);
                    activeLayout.setLayout(layout);
                    popup.hide();
                    AG.Sortable.update();
                    e.preventDefault()
                })
            });
            this.editLayout = (function () {
                popup.show();
                AJS.$(document).keyup(function (e) {
                    if (e.keyCode === 27) {
                        popup.hide();
                        AJS.$(document).unbind("keyup", arguments.callee);
                        e.preventDefault()
                    }
                });
                return arguments.callee
            }())
        },
        getLayout: function () {
            return this.activeLayout
        },
        markReadOnlyLayouts: function () {
            AJS.$.each(layouts, function () {
                if (!this.isWritable()) {
                    this.markReadOnlyLayout()
                }
            })
        },
        unmarkReadOnlyLayouts: function () {
            AJS.$.each(layouts, function () {
                if (!this.isWritable()) {
                    this.unmarkReadOnlyLayout()
                }
            })
        },
        setLayout: function (layout) {
            this.activeLayout = layout
        },
        addGadget: function (gadget, column) {
            this.activeLayout.addGadget(gadget, column)
        },
        setup: function (options) {
            var that = this,
                securityTokenRefreshRate = AJS.parseUri(document.location.href).queryKey["__st_refresh"] || 1000 * 60 * 12;
            console.debug = console.debug ||
            function () {};
            AJS.$.aop.after({
                target: gadgets.IfrGadgetService.prototype,
                method: "setHeight"
            }, function () {
                that.getLayout().onInit(function () {
                    that.getLayout().refresh()
                })
            });
            AG.param.set(options.params);
            AG.render.ready(function () {
                AJS.$(function () {
                    AG.Sortable.init();
                    dashboard = AJS.$("#dashboard");
                    dashboard.header = AJS.$("<div id='dashboard-header' />").appendTo(dashboard);
                    if (options.layouts.length > 1) {
                        that.getDashboard().addClass("v-tabs");
                        dashboard.tabContainer = AJS.$("<ul class='vertical tabs' />").appendTo(dashboard)
                    }
                    dashboard.contents = AJS.$("<div id='dashboard-content' />").appendTo(dashboard);
                    if (options.menu.items && options.menu.items.length > 0) {
                        dashboard.menu = createMenu(options.menu)
                    }
                    dashboard.shim = AJS.$('<div class="dashboard-shim"> </div>').appendTo(dashboard.contents);
                    AJS.$.each(options.layouts, function () {
                        that.addLayout(this)
                    });
                    dashboard.removeClass("initializing");

                    function updateSecurityTokens() {
                        var gadgetTokenFrames = new Array(),
                            updateTokenParams = {};
                        console.debug("Updating all gadget security tokens");
                        AJS.$.each(AG.DashboardManager.getLayout().getGadgets(), function (index) {
                            gadgetTokenFrames.push({
                                gadget: this,
                                iframeId: this.getElement().find("iframe.gadget-iframe").attr("id")
                            });
                            updateTokenParams["st." + index] = this.getSecurityToken()
                        });
                        if (!updateTokenParams["st.0"]) {
                            console.debug("No gadgets on dashboard, so there is no need to update security tokens.");
                            return
                        }
                        AJS.$.ajax({
                            type: "POST",
                            url: AG.param.get("securityTokensUrl"),
                            data: updateTokenParams,
                            dataType: "json",
                            success: function (newSecurityTokens) {
                                AJS.$.each(gadgetTokenFrames, function (index) {
                                    this.gadget.setSecurityToken(newSecurityTokens["st." + index]);
                                    try {
                                        gadgets.rpc.call(this.iframeId, "update_security_token", null, this.gadget.getSecurityToken())
                                    } catch (e) {
                                        console.debug("Unable to update the security token for gadget with iframe id " + this.iframeId + ".  This likely means that the gadget does not use the " + "'auth-refresh' feature.  If the gadget uses gadgets.io.makeRequest after its" + "initial startup, it is a good idea to use the 'auth-refresh' feature " + "by adding <Optional feature='auth-refresh' /> to your gadget's " + "<ModulePrefs> section.  Otherwise, the gadget's security token could expire" + " and subsequent calls to gadgets.io.makeRequest will fail.")
                                    }
                                });
                                console.debug("Updating security tokens complete.")
                            },
                            error: function (request, textStatus, errorThrown) {
                                if (request.status != 200) {
                                    console.debug("Failed to get new security tokens. Response was had a status of '" + request.status + "' saying '" + request.statusText + "'")
                                } else {
                                    console.debug("There was an error processing the response. Error was '" + textStatus + "'")
                                }
                            }
                        })
                    }
                    console.debug("Security tokens will be refreshed every " + securityTokenRefreshRate + "ms");
                    window.setInterval(updateSecurityTokens, securityTokenRefreshRate);
                    that.doDiagnostics()
                })
            });
            AG.render.initialize()
        }
    }
}());
(function () {
    if (typeof Object.create !== "function") {
        Object.create = function (o) {
            function F() {}
            F.prototype = o;
            return new F()
        }
    }
    var LayoutManager = {
        saveLayout: function () {
            var that = this;

            function getData() {
                return AJS.$.extend({
                    layout: that.layout
                }, AG.Sortable.serialize())
            }
            AJS.$.ajax({
                type: "post",
                url: AG.param.get("layoutAction"),
                contentType: "application/json",
                data: JSON.stringify(getData()),
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("X-HTTP-Method-Override", "PUT")
                },
                success: function () {
                    if (AJS.debug) {
                        console.log("AG.LayoutManager.saveLayout: Layout (" + that.layout + ") saved successfully")
                    }
                },
                error: function (request) {
                    if (request.status == 403 || request.status == 401) {
                        alert(AG.param.get("dashboardErrorDashboardPermissions"))
                    } else {
                        alert(AG.param.get("dashboardErrorCouldNotSave"))
                    }
                    if (AJS.debug) {
                        console.log("AG.LayoutManager.saveLayout: Request failed! Printing response object...");
                        console.log(request)
                    }
                }
            })
        },
        getColumn: function (idx) {
            var that = this,
                i = parseInt(idx, 16);
            if (arguments.length) {
                return that.columns
            } else {
                if (!isNaN(i) || !that.columns[i]) {
                    return that.columns.eq(i)
                } else {
                    if (AJS.debug) {
                        console.error("AG.LayoutManager.getColumn: The column index you provided is invalid. " + "Expected a number in the range of 0-" + that.columns.length - 1 + " but recieved " + idx)
                    }
                }
            }
        },
        setLayout: function (layout, save) {
            layout = AJS.$.trim(layout);
            if (this.layout === layout) {
                if (AJS.debug) {
                    console.warn("AG.LayoutManager.setLayout: Ignoring! The layout supplied is the same as the current " + "layout (" + layout + ")")
                }
                return
            }
            if (AJS.$.inArray(layout, AG.LayoutManager.layouts) === -1) {
                if (AJS.debug) {
                    console.error("AG.LayoutManager.setLayout: Invalid layout! Was given " + layout + ", but expected " + "either of '" + AG.LayoutManager.layouts.toString() + "'")
                }
            }
            this.container.addClass("layout-" + layout.toLowerCase());
            if (!this.isWritable()) {
                if (AJS.debug) {
                    console.log("AG.LayoutManager.setLayout: Can't manipulate layout. Layout is not writable")
                }
                return
            }
            if (this.layout) {
                this.container.removeClass("layout-" + this.layout.toLowerCase())
            }
            AJS.$.each(this.gadgets, function () {
                var layoutRep = this.getElement().layoutRep,
                    prevColumn = layoutRep.parent().prev();
                if (!layoutRep.is(":visible")) {
                    if (prevColumn.is(":visible")) {
                        prevColumn.append(layoutRep)
                    } else {
                        prevColumn.prev().append(layoutRep)
                    }
                }
            });
            if (layout === "AB" || layout === "BA" || layout === "AA") {
                this.columns.eq(0).addClass("sortable");
                this.columns.eq(1).addClass("sortable");
                this.columns.eq(2).removeClass("sortable")
            } else {
                if (layout === "A") {
                    this.columns.eq(0).addClass("sortable");
                    this.columns.eq(1).removeClass("sortable");
                    this.columns.eq(2).removeClass("sortable")
                } else {
                    if (layout === "AAA") {
                        this.columns.eq(0).addClass("sortable");
                        this.columns.eq(1).addClass("sortable");
                        this.columns.eq(2).addClass("sortable")
                    }
                }
            }
            this.layout = layout;
            this.refresh();
            if (save !== false) {
                this.saveLayout()
            } else {
                if (AJS.debug) {
                    console.log("AG.LayoutManager.setLayout: Layout successfully set to '" + this.layout + "'")
                }
            }
        },
        getGadgets: function () {
            return this.gadgets
        },
        removeGadget: function (gadget) {
            var that = this;
            AJS.$.each(this.gadgets, function (idx) {
                if (this === gadget) {
                    that.gadgets.splice(idx, 1);
                    return false
                }
            })
        },
        deactivate: function () {
            this.container.hide();
            AJS.$.each(this.gadgets, function () {
                if (this.getElement().layoutRep.css("display") === "list-item") {
                    this.getElement().hide()
                }
            })
        },
        activate: function () {
            this.container.show();
            AJS.$.each(this.gadgets, function () {
                this.getElement().show()
            });
            this.refresh()
        },
        refresh: function () {
            var that = this,
                isIE6OrBelow = !! (AJS.$.browser.msie && parseInt(jQuery.browser.version) <= 6);

            function appendEmptyMsgElem(col, idx) {
                var message = AG.param.get("dragHere", "<a class='add-gadget-link' id='add-gadget-" + idx + "' href='#'>", "</a>");
                return AJS.$("<li class='empty-text'>" + message + "</li>").appendTo(col)
            }
            function isCanvasMode() {
                return !!AJS.$(".layout.maximized").size()
            }
            if (!this.initialized && !isCanvasMode()) {
                return
            }
            if (!AG.DashboardManager.getDashboard().hasClass("dragging")) {
                this.columns.css(isIE6OrBelow ? "height" : "minHeight", "");
                this.columns.filter(":visible").each(function (idx) {
                    var column = AJS.$(this);
                    if (AJS.$("li:visible:not(.empty-text)", column).length === 0) {
                        column.addClass("empty");
                        if (that.isWritable()) {
                            if (!this.msgElem) {
                                this.msgElem = appendEmptyMsgElem(column, idx)
                            } else {
                                if (this.msgElem) {
                                    this.msgElem.show()
                                }
                            }
                        }
                    } else {
                        if (column.hasClass("empty")) {
                            column.removeClass("empty");
                            if (this.msgElem) {
                                this.msgElem.hide()
                            }
                        }
                    }
                })
            }
            AJS.$("li.gadget", this.container).each(function () {
                this.getGadgetInstance().updatePosition()
            });
            if (!AG.DashboardManager.getDashboard().hasClass("dragging")) {
                this.columns.each(function () {
                    var column = AJS.$(this);
                    column.css(isIE6OrBelow ? "height" : "minHeight", column.parent().height())
                })
            }
        },
        addGadget: function (gadget, column) {
            var that = this,
                rpctoken;

            function hideGadget() {
                gadget.getElement().layoutRep.addClass("hidden");
                gadget.getElement().hide();
                gadget.getLayoutManager().refresh()
            }
            function showGadget() {
                delete gadget.hasBeenDropped;
                gadget.getElement().layoutRep.removeClass("hidden");
                gadget.getElement().show();
                gadget.getLayoutManager().refresh()
            }
            function validateAdd(numGadgets) {
                if (parseInt(numGadgets) >= AG.param.get("maxGadgets")) {
                    showGadget();
                    alert(AG.param.get("dashboardErrorTooManyGadgets"))
                } else {
                    gadget.move(that.options.resourceUrl)
                }
            }
            function appendToColumn() {
                if (!that.initialized) {
                    that.columns.eq(column).append(gadget.getElement().layoutRep)
                } else {
                    that.columns.eq(column).prepend(gadget.getElement().layoutRep)
                }
            }
            function isFromDifferentLayout() {
                return AJS.$.isFunction(gadget.getLayoutManager)
            }
            function ensureIframeDoesntCache() {
                AJS.$("iframe", gadget.getElement()).each(function () {
                    this.src = this.src;
                    this.contentWindow.location = this.src
                })
            }
            if (!isFromDifferentLayout()) {
                column = column || gadget.column || 0;
                gadget = gadget.loaded ? gadget : AG.Gadget.getNullGadgetRepresentation(gadget);
                rpctoken = Math.round(Math.random() * 10000000);
                if (gadget.renderedGadgetUrl.indexOf("#rpctoken") == -1) {
                    gadget.renderedGadgetUrl += "#rpctoken=" + rpctoken
                } else {
                    gadget.renderedGadgetUrl = gadget.renderedGadgetUrl.replace(/#rpctoken=\d*/, "#rpctoken=" + rpctoken)
                }
                gadget.layout = this.options;
                gadget = AG.Gadget(gadget);
                appendToColumn();
                AG.DashboardManager.getDashboard().contents.append(gadget.getElement());
                gadget.updatePosition();
                gadgets.rpc.setAuthToken(gadget.getElement().find("iframe").attr("id"), rpctoken);
                ensureIframeDoesntCache();
                AG.Sortable.update()
            } else {
                hideGadget();
                AJS.$.get(this.options.resourceUrl + "/numGadgets", function (numGadgets) {
                    validateAdd(numGadgets)
                })
            }
            this.refresh();
            this.gadgets.push(gadget);
            return gadget
        },
        markReadOnlyLayout: function () {
            if (!this.isWritable()) {
                this.tab.addClass("inactive")
            }
        },
        onInit: function (callback) {
            if (!this.initialized) {
                this.onInit.callbacks = this.onInit.callbacks || [];
                this.onInit.callbacks.push(callback)
            } else {
                callback()
            }
        },
        unmarkReadOnlyLayout: function () {
            if (!this.isWritable() && this.tab.hasClass("inactive")) {
                this.tab.removeClass("inactive")
            }
        },
        isWritable: function () {
            return this.options.writable
        },
        getPublicInstance: function () {
            var that = this;
            if (!this.publicInterface) {
                this.publicInterface = {
                    unmarkReadOnlyLayout: function () {
                        return that.unmarkReadOnlyLayout.apply(that, arguments)
                    },
                    markReadOnlyLayout: function () {
                        return that.markReadOnlyLayout.apply(that, arguments)
                    },
                    isWritable: function () {
                        return that.isWritable.apply(that, arguments)
                    },
                    activate: function () {
                        return that.activate.apply(that, arguments)
                    },
                    deactivate: function () {
                        return that.deactivate.apply(that, arguments)
                    },
                    getGadgets: function () {
                        return that.getGadgets.apply(that, arguments)
                    },
                    getLayout: function () {
                        return that.layout
                    },
                    getContainer: function () {
                        return that.container
                    },
                    getColumn: function () {
                        return that.columns
                    },
                    setLayout: function () {
                        return that.setLayout.apply(that, arguments)
                    },
                    addGadget: function () {
                        return that.addGadget.apply(that, arguments)
                    },
                    removeGadget: function () {
                        return that.removeGadget.apply(that, arguments)
                    },
                    refresh: function () {
                        return that.refresh.apply(that, arguments)
                    },
                    init: function () {
                        return that.init.apply(that, arguments)
                    },
                    saveLayout: function () {
                        return that.saveLayout.apply(that, arguments)
                    },
                    getId: function () {
                        return that.options.id
                    },
                    onInit: function () {
                        return that.onInit.apply(that, arguments)
                    }
                }
            }
            return this.publicInterface
        },
        init: function () {
            var that = this,
                canvasGadget;
            this.gadgets = [];
            this.options.gadgets = this.options.gadgets || [];

            function getCanvasGadgetRepresentation(gadgets) {
                var canvasGadget;
                AJS.$.each(that.options.gadgets, function () {
                    if (AG.Gadget.isCanvasView(this.id)) {
                        canvasGadget = this;
                        return false
                    }
                });
                return canvasGadget
            }
            function fitTab(label, capacity) {
                var labelText = label.text();
                while (label.width() >= capacity && labelText.length >= 3) {
                    labelText = labelText.slice(0, labelText.length - 1);
                    label.text(labelText + "...")
                }
            }
            function appendTab() {
                var labelSpan = AJS.$("<span />").text(that.options.title).attr("title", that.options.title),
                    labelStrong = AJS.$("<strong />").append(labelSpan),
                    capacity;
                that.tab = AJS.$("<li />");
                if (that.options.uri) {
                    that.tab.append(AJS.$("<a href='" + that.options.uri + "' />").append(labelStrong))
                } else {
                    that.tab.append(labelStrong);
                    that.tab.addClass("active")
                }
                that.tab.get(0).getLayoutInstance = function () {
                    return that.getPublicInstance()
                };
                that.tab.appendTo(AG.DashboardManager.getDashboard().tabContainer);
                capacity = AG.DashboardManager.getDashboard().tabContainer.innerWidth() - parseInt(labelStrong.css("padding-left")) - parseInt(labelStrong.css("padding-right"));
                fitTab(labelSpan, capacity);
                AJS.$("li:first", AG.DashboardManager.getDashboard().tabContainer).addClass("first");
                if (that.isWritable() && that.options.active === false) {
                    AG.Sortable.addHotSpot(that.tab, function (gadget) {
                        that.addGadget(gadget)
                    })
                }
            }
            function appendColumns() {
                that.container = AJS.$("<div class='layout' />").appendTo(AG.DashboardManager.getDashboard().contents);
                that.columns = AJS.$("<ul />").addClass("column first").add(AJS.$("<ul />").addClass("column second")).add(AJS.$("<ul />").addClass("column third")).appendTo(that.container)
            }
            function appendGadgets() {
                AJS.$.each(that.options.gadgets, function () {
                    that.addGadget(this)
                })
            }
            function setInitialized() {
                that.initialized = true;
                if (that.onInit.callbacks) {
                    AJS.$.each(that.onInit.callbacks, function () {
                        this()
                    })
                }
                that.refresh()
            }
            if (AG.DashboardManager.getDashboard().tabContainer) {
                appendTab()
            }
            if (this.options.active !== false) {
                appendColumns();
                this.setLayout(this.options.layout, false);
                canvasGadget = getCanvasGadgetRepresentation(this.options.gadgets);
                if (canvasGadget) {
                    canvasGadget = this.addGadget(canvasGadget);
                    canvasGadget.setView("canvas");
                    canvasGadget.updatePosition();
                    AJS.$.aop.after({
                        target: canvasGadget,
                        method: "setView"
                    }, function () {
                        canvasGadget.remove();
                        that.removeGadget(canvasGadget);
                        appendGadgets();
                        setInitialized()
                    })
                } else {
                    appendGadgets();
                    setInitialized()
                }
            }
        }
    };
    AG.LayoutManager = function (options) {
        var layoutManager = Object.create(LayoutManager);
        layoutManager.options = options;
        return layoutManager.getPublicInstance()
    };
    AG.LayoutManager.layouts = ["A", "AA", "BA", "AB", "AAA"];
    AG.LayoutManager.getLayoutAttrName = function (layout) {
        return "layout-" + layout.toLowerCase()
    }
}());
(function () {
    function FauxList(listContainer) {
        var that = this,
            ENTER_KEY = 13;
        this.container = AJS.$(listContainer);
        this.values = AJS.$("input.list", this.container).hide().val().split("|");
        this.originalValues = this.values.join("|").split("|");
        this.container.append('<input class="add-to-list text med js" type="text" value="" />' + '<button class="submit-to-list js">' + AG.param.get("add") + "</button>");
        this.container.children(".submit-to-list").click(function (e) {
            that.addToList();
            e.preventDefault()
        });
        AJS.$("input.add-to-list", this.container).keydown(function (e) {
            if (e.keyCode == ENTER_KEY) {
                that.addToList();
                e.preventDefault()
            }
        });
        AJS.$(".description", this.container).appendTo(this.container);
        this.create(this.values)
    }
    FauxList.prototype = {
        reset: function () {
            this.create(this.originalValues)
        },
        create: function (values) {
            var ul, listItem, that = this;
            if (values) {
                AJS.$.each(values, function () {
                    if (this == "") {
                        values.splice(values.indexOf(this), 1)
                    }
                });
                ul = AJS.$('<ul class="faux-list"></ul>');
                if (values.length > 0) {
                    for (var i = 0, ii = values.length; i < ii; i++) {
                        listItem = AJS.$('<li class="listvalue-' + i + '"><span>' + values[i] + '</span><a class="remove" href="#remove-from-list" title="' + AG.param.get("removeFromList") + '">x</a></li>');
                        AJS.$("a", listItem).click(function (e) {
                            var removeValue = AJS.$(this).parent("li").attr("class").split("-")[1];
                            values.splice(removeValue, 1);
                            if (values.length > 0) {
                                that.create(values)
                            } else {
                                AJS.$("input.list", this.container).val("")
                            }
                            listItem.remove();
                            e.preventDefault()
                        });
                        ul.append(listItem)
                    }
                    if (AJS.$("ul.faux-list", this.container).length == 0) {
                        AJS.$("input.list", this.container).before(ul)
                    } else {
                        AJS.$("ul.faux-list", this.container).replaceWith(ul)
                    }
                } else {
                    AJS.$("ul.faux-list", this.container).remove()
                }
                AJS.$("input.list", this.container).val(values.join("|"));
                AG.DashboardManager.getLayout().refresh()
            }
        },
        addToList: function () {
            var newValue = AJS.$("input.add-to-list", this.container).val().replace(/\|+/g, "%7C");
            this.values.push(newValue);
            AJS.$("input.add-to-list", this.container).val("");
            this.create(this.values)
        }
    };
    var Gadget = {
        draw: function (json) {
            var that = this;

            function createElement() {
                json.minimized = that.minimized;
                json.view = that.view;
                that.$ = AJS.$(AG.render("gadget", json));
                that.$.updateShadow = function () {
                    var attrs = {
                        width: that.$.width() + 32,
                        height: that.$.height() + 29
                    };
                    that.$.shadow.sides.css("height", attrs.height - 46);
                    that.$.shadow.bottom.css("width", attrs.width - 58);
                    that.$.shadow.css(attrs)
                }
            }
            function setHeightFromCookie() {
                if (json) {
                    var height = AG.Cookie.read("gadget-" + json.id + "-fh", null);
                    if (!isNaN(parseInt(height))) {
                        json = AJS.$.extend(json, {
                            height: height
                        })
                    }
                }
            }
            function setElementShortcuts() {
                that.$.layoutRep = AJS.$("<li class='gadget' id='rep-" + json.id + "' />").height(that.$.height());
                that.$.shadow = AJS.$("div.shadow", that.$);
                that.$.shadow.bottom = AJS.$("div.b", that.$.shadow);
                that.$.shadow.sides = AJS.$("div.l", that.$.shadow).add(AJS.$("div.r", that.$.shadow));
                that.$.layoutRep.get(0).getGadgetInstance = that.$.get(0).getGadgetInstance = function () {
                    return that.getPublicInstance()
                }
            }
            function applyDropdownControls() {
                var ACTIVE_CLASS = "dropdown-active",
                    ddParent = AJS.$("li.aui-dd-parent", that.$);
                ddParent.mousedown(function (e) {
                    e.stopPropagation()
                });
                that.$.dropdown = ddParent.dropDown("standard", {
                    selectionHandler: function (e) {
                        e.preventDefault()
                    },
                    item: "> li"
                })[0];
                that.$.dropdown.addCallback("show", function () {
                    that.$.addClass(ACTIVE_CLASS);
                    that.$.updateShadow();
                    AG.DashboardManager.showShims()
                });
                that.$.dropdown.addCallback("hide", function () {
                    that.$.removeClass(ACTIVE_CLASS);
                    AG.DashboardManager.hideShims()
                });
                that.$.hover(function () {}, function () {
                    if (that.$.dropdown.$.is(":visible")) {
                        that.$.dropdown.hide()
                    }
                })
            }
            function applyGadgetHoverControls() {
                var HOVER_CLASS = "gadget-hover";
                that.$.hover(function () {
                    AJS.$(".gadget-container", that.$).addClass(HOVER_CLASS)
                }, function () {
                    AJS.$(".gadget-container", that.$).removeClass(HOVER_CLASS)
                })
            }
            function applyColorControls() {
                AJS.$(".gadget-colors a", that.$).click(function (e) {
                    that.setColor(this.parentNode.className);
                    e.preventDefault()
                })
            }
            function applyMinimizeControls() {
                var menuElem = AJS.$("a.minimization, a.maximization", that.$),
                    titleElem = AJS.$(".dashboard-item-title", that.$),
                    maxMinToggle = function (e) {
                        if (that.minimized) {
                            that.maximize()
                        } else {
                            that.minimize()
                        }
                        AJS.$(this).one(e.type, function (e) {
                            if (that.minimized) {
                                that.maximize()
                            } else {
                                that.minimize()
                            }
                            AJS.$(this).one(e.type, maxMinToggle)
                        })
                    };
                titleElem.one("dblclick", maxMinToggle);
                menuElem.one("click", maxMinToggle);
                if (AJS.$.browser.safari) {
                    titleElem.get(0).onselectstart = function () {
                        return false
                    }
                }
            }
            function applyFocusControls() {
                var column;
                AJS.$(".dashboard-item-header", that.$).mousedown(function (e) {
                    if (!that.$.hasClass("maximized") || AG.DashboardManager.getDashboard().hasClass("v-tabs")) {
                        if (!column) {
                            column = that.$.layoutRep.parent()
                        }
                        that.$.dropdown.hide();
                        that.$.focusTimeout = setTimeout(function () {
                            that.$.updateShadow();
                            that.$.shadow.show();
                            delete that.$.focusTimeout
                        }, 150);
                        that.$.layoutRep.trigger(e)
                    }
                });
                that.$.mouseup(function () {
                    if (that.$.focusTimeout) {
                        clearTimeout(that.$.focusTimeout)
                    } else {
                        if (that.$.layoutRep.is(":visible")) {
                            that.$.stop(true, true);
                            that.$.shadow.hide()
                        }
                    }
                })
            }
            function applyUserPrefControls() {
                var fauxLists = [],
                    prefForm = AJS.$(".userpref-form", that.$),
                    prefsChanged = false,
                    savePrefForm = function (success) {
                        var formArray = prefForm.serializeArray(),
                            submittedState = {};
                        AJS.$.each(formArray, function () {
                            submittedState[this.name] = this.value || ""
                        });
                        AJS.$(":checkbox:not(:checked)", prefForm).each(function () {
                            submittedState[this.name] = false
                        });
                        AJS.$.ajax({
                            url: prefForm.attr("action"),
                            type: "POST",
                            contentType: "application/json",
                            data: JSON.stringify(submittedState),
                            beforeSend: function (xhr) {
                                xhr.setRequestHeader("X-HTTP-Method-Override", "PUT")
                            },
                            dataType: "text",
                            success: success
                        })
                    };
                if (that.isEditable()) {
                    AJS.$(".list-container", that.$).each(function () {
                        fauxLists.push(new FauxList(this))
                    });
                    AJS.$(".edit", that.$).click(function (e) {
                        if (!prefForm.is(":visible")) {
                            if (that.minimized) {
                                that.maximize()
                            }
                            prefForm.show();
                            that.getLayoutManager().refresh()
                        } else {
                            prefForm.hide();
                            that.getLayoutManager().refresh()
                        }
                        e.preventDefault()
                    });
                    prefForm.submit(function (e) {
                        savePrefForm(function () {
                            window.location.reload()
                        });
                        e.preventDefault()
                    });
                    AJS.$(":reset", prefForm).click(function () {
                        AJS.$.each(fauxLists, function () {
                            this.reset()
                        });
                        prefForm.hide();
                        that.getLayoutManager().refresh()
                    })
                }
                AJS.$("iframe.gadget-iframe", that.$).bind("setUserPref", function (e) {
                    for (var i = 1, j = arguments.length; i < j; i += 2) {
                        if (pref_name = arguments[i]) {
                            var pref_value = arguments[i + 1];
                            var input = AJS.$(":input[name='up_" + pref_name + "']", prefForm);
                            if (input.attr("type") == "checkbox") {
                                input.attr("checked", pref_value)
                            } else {
                                input.val(pref_value)
                            }
                        }
                    }
                    if (!prefsChanged) {
                        setTimeout(function () {
                            savePrefForm(function () {});
                            prefsChanged = false
                        }, 100);
                        prefsChanged = true
                    }
                })
            }
            function applyDeleteControls() {
                AJS.$("a.delete", that.$).bind("click", function (e) {
                    that.destroy();
                    e.preventDefault()
                })
            }
            function applyViewToggleControls() {
                AJS.$("a.maximize", that.$).click(function (e) {
                    if (!AG.Gadget.isCanvasView(that.id)) {
                        that.getPublicInstance().setView("canvas");
                        e.preventDefault()
                    } else {
                        that.getPublicInstance().setView("default");
                        e.preventDefault()
                    }
                })
            }
            function applyErrorMessage() {
                AJS.$("iframe.gadget-iframe", that.$).load(function () {
                    AJS.$("#error-gadget-message", AJS.$(this).contents()).html(that.errorMessage)
                })
            }
            setHeightFromCookie();
            createElement();
            setElementShortcuts();
            applyDropdownControls();
            applyGadgetHoverControls();
            applyMinimizeControls();
            if (this.isMaximizable) {
                applyViewToggleControls()
            }
            if (!this.loaded) {
                applyErrorMessage()
            }
            if (this.getLayoutManager().isWritable()) {
                applyDeleteControls();
                applyFocusControls();
                applyColorControls();
                applyUserPrefControls()
            }
        },
        isEditable: function () {
            return !!(this.getLayoutManager().isWritable() && this.hasNonHiddenUserPrefs)
        },
        setLayoutManager: function (layoutManager) {
            if (layoutManager) {
                this.layoutManager = layoutManager
            } else {
                this.layoutManager = AG.DashboardManager.getLayout()
            }
        },
        getLayoutManager: function () {
            if (!this.layoutManager) {
                this.setLayoutManager()
            }
            return this.layoutManager
        },
        setColor: function (color) {
            var that = this;
            that.$.removeClass(that.color).addClass(color);
            that.color = color;
            AJS.$.ajax({
                type: "post",
                url: that.colorUrl,
                contentType: "application/json",
                data: JSON.stringify({
                    color: color
                }),
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("X-HTTP-Method-Override", "PUT")
                },
                error: function (request) {
                    if (request.status == 403 || request.status == 401) {
                        alert(AG.param.get("dashboardErrorDashboardPermissions"))
                    } else {
                        alert(AG.param.get("dashboardErrorCouldNotSave"))
                    }
                }
            })
        },
        updatePosition: function () {
            var gadgetCSSToUpdate, layoutCSSToUpdate, that = this;

            function isGadgetBeingDragged() {
                return that.$.hasClass("dragging")
            }
            function getCurrentGadgetCSS() {
                var LAYOUT_REP_OFFSET, dashboard = AG.DashboardManager.getDashboard().contents,
                    DASHBOARD_OFFSET = dashboard.offset();
                if (!getCurrentGadgetCSS.cache) {
                    LAYOUT_REP_OFFSET = that.$.layoutRep.offset();
                    getCurrentGadgetCSS.cache = {
                        left: (LAYOUT_REP_OFFSET.left - DASHBOARD_OFFSET.left) / dashboard.width() * 100 + "%",
                        top: LAYOUT_REP_OFFSET.top - DASHBOARD_OFFSET.top,
                        width: that.$.layoutRep.width() / dashboard.width() * 100 + "%"
                    }
                }
                return getCurrentGadgetCSS.cache
            }
            function getCurrentLayoutRepCSS() {
                if (!getCurrentLayoutRepCSS.cache) {
                    getCurrentLayoutRepCSS.cache = {
                        height: that.$.height()
                    }
                }
                return getCurrentLayoutRepCSS.cache
            }
            function filterModifiedCSS(lastRecordedCSS, currentCSS) {
                if (lastRecordedCSS) {
                    AJS.$.each(lastRecordedCSS, function (property) {
                        if (this === currentCSS[property]) {
                            delete currentCSS[property]
                        }
                    })
                }
                return currentCSS
            }
            if (!isGadgetBeingDragged()) {
                layoutCSSToUpdate = filterModifiedCSS(this.$.layoutRep.lastRecordedCSS, getCurrentLayoutRepCSS());
                this.$.layoutRep.css(layoutCSSToUpdate);
                this.$.layoutRep.lastRecordedCSS = layoutCSSToUpdate;
                gadgetCSSToUpdate = filterModifiedCSS(this.$.lastRecordedCSS, getCurrentGadgetCSS());
                this.$.css(gadgetCSSToUpdate);
                this.$.lastRecordedCSS = gadgetCSSToUpdate;
                if (this.$.hasClass("hidden")) {
                    this.$.removeClass("hidden")
                }
            }
        },
        maximize: function () {
            var MIN_CLASS = "minimization",
                MAX_CLASS = "maximization",
                MIN_TEXT = AG.param.get("minimize"),
                menuElem = AJS.$("a.minimization, a.maximization", this.$);
            menuElem.removeClass(MAX_CLASS).addClass(MIN_CLASS).text(MIN_TEXT);
            this.$.css({
                height: "auto"
            });
            AJS.$(".dashboard-item-content", this.$).removeClass(MIN_CLASS);
            this.getLayoutManager().refresh();
            AG.Cookie.erase(this.COOKIE_MINIMIZE);
            this.minimized = false
        },
        minimize: function () {
            var MIN_CLASS = "minimization",
                MAX_CLASS = "maximization",
                MAX_TEXT = AG.param.get("expand"),
                menuElem = AJS.$("a.minimization, a.maximization", this.$);
            menuElem.removeClass(MIN_CLASS).addClass(MAX_CLASS).text(MAX_TEXT);
            this.$.css({
                height: "auto"
            });
            AJS.$(".dashboard-item-content", this.$).addClass(MIN_CLASS);
            this.getLayoutManager().refresh();
            AG.Cookie.save(this.COOKIE_MINIMIZE, "true");
            this.minimized = true
        },
        remove: function () {
            var that = this;
            window.setTimeout(function () {
                that.$.layoutRep.remove();
                that.$.remove();
                that.getLayoutManager().removeGadget(that.getPublicInstance());
                that.getLayoutManager().refresh();
                AJS.$.each(this, function (name, property) {
                    property = null
                });
                AG.Cookie.erase("gadget-" + that.id + "-fh")
            }, 10)
        },
        move: function (targetResourceUrl) {
            this.remove();
            AJS.$(AJS.$.ajax({
                type: "post",
                data: {
                    id: this.id,
                    title: this.title,
                    titleUrl: this.titleUrl,
                    gadgetSpecUrl: this.gadgetSpecUrl,
                    height: this.$.height(),
                    width: this.$.width(),
                    color: this.color,
                    isMaximizable: this.isMaximizable,
                    userPrefs: this.userPrefs,
                    renderedGadgetUrl: this.renderedGadgetUrl,
                    colorUrl: this.colorUrl,
                    gadgetUrl: this.gadgetUrl,
                    hasNonHiddenUserPrefs: this.hasNonHiddenUserPrefs,
                    column: this.column,
                    loaded: this.loaded
                },
                contentType: "application/json",
                url: targetResourceUrl + "/gadget/" + this.id,
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("X-HTTP-Method-Override", "PUT")
                }
            })).throbber({
                target: AJS.$("#dash-throbber")
            })
        },
        destroy: function () {
            var that = this;
            if (confirm(AG.param.get("areYouSure") + " " + that.title + " " + AG.param.get("gadget"))) {
                AJS.$.ajax({
                    type: "POST",
                    url: this.gadgetUrl,
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("X-HTTP-Method-Override", "DELETE")
                    },
                    success: function () {
                        that.$.fadeOut(function () {
                            that.remove();
                            if (that.view === "canvas") {
                                that.setView("default")
                            }
                        })
                    },
                    error: function (request) {
                        if (request.status == 403 || request.status == 401) {
                            alert(AG.param.get("dashboardErrorDashboardPermissions"))
                        } else {
                            alert(AG.param.get("dashboardErrorCouldNotSave"))
                        }
                    }
                })
            }
        },
        setView: function (view) {
            var MAXIMIZED_CLASS = "maximized",
                uri, that = this,
                anchor = this.title.replace(/\s/g, "-") + "/" + this.id,
                layoutManager = this.getLayoutManager(),
                rpctoken;

            function toDefaultViewHandler() {
                that.getPublicInstance().setView("default")
            }
            if (this.view === view) {
                return
            }
            if (view === "canvas" || view === "default") {
                AJS.$.ajax({
                    async: false,
                    type: "GET",
                    url: this.gadgetUrl,
                    dataType: "json",
                    success: function (rep) {
                        rpctoken = Math.round(Math.random() * 10000000);
                        uri = AJS.parseUri(rep.renderedGadgetUrl + "#rpctoken=" + rpctoken)
                    }
                });
                AJS.$(".operations li", AG.DashboardManager.getDashboard()).toggleClass("hidden");
                gadgets.rpc.setAuthToken(AJS.$("iframe.gadget-iframe", this.$).attr("id"), rpctoken);
                if (view === "canvas") {
                    AJS.$.extend(uri.queryKey, {
                        view: "canvas"
                    });
                    AJS.$("iframe.gadget-iframe", this.$).attr("src", uri.toString());
                    layoutManager.getContainer().addClass(MAXIMIZED_CLASS);
                    AJS.$(".gadget-container", this.$).addClass(MAXIMIZED_CLASS);
                    this.$.addClass(MAXIMIZED_CLASS);
                    AJS.$(".aui-icon", this.$).attr("title", AG.param.get("restoreFromCanvasMode"));
                    this.$.layoutRep.addClass(MAXIMIZED_CLASS);
                    this.$.layoutRep.parent().addClass(MAXIMIZED_CLASS);
                    AJS.$.each(this.getLayoutManager().getGadgets(), function () {
                        if (that.getPublicInstance() !== this) {
                            this.getElement().hide()
                        }
                    });
                    AJS.$.extend(uri.queryKey, {
                        view: "canvas"
                    });
                    AJS.$("iframe.gadget-iframe", this.$).attr("src", uri.toString());
                    this.maximize();
                    window.location.href = window.location.href.replace(/#.*/, "") + "#" + anchor;
                    AJS.$(".minimize", AG.DashboardManager.getDashboard()).click(toDefaultViewHandler);
                    this.view = "canvas"
                } else {
                    layoutManager.getContainer().removeClass(MAXIMIZED_CLASS);
                    AJS.$(".gadget-container", this.$).removeClass(MAXIMIZED_CLASS);
                    this.$.removeClass(MAXIMIZED_CLASS);
                    AJS.$(".aui-icon", this.$).attr("title", AG.param.get("maximize"));
                    this.$.layoutRep.removeClass(MAXIMIZED_CLASS);
                    this.$.layoutRep.parent().removeClass(MAXIMIZED_CLASS);
                    AJS.$.each(this.getLayoutManager().getGadgets(), function () {
                        if (that.getPublicInstance() !== this) {
                            this.getElement().show()
                        }
                    });
                    AJS.$.extend(uri.queryKey, {
                        view: "default"
                    });
                    AJS.$("iframe.gadget-iframe", this.$).attr("src", uri.toString());
                    this.getLayoutManager().refresh();
                    window.location.href = window.location.href.replace(anchor, "");
                    AJS.$("a.minimize", AG.DashboardManager.getDashboard()).unbind("click", toDefaultViewHandler);
                    this.view = "default"
                }
            } else {
                if (AJS.debug) {
                    console.warn("AG.Gadget.setView: Ignored! not a valid view. Was supplied '" + view + "' but expected " + "either 'default' or 'canvas'")
                }
            }
        },
        editPrefs: function () {},
        getPublicInstance: function () {
            var gadget = this;
            if (!this.publicInterface) {
                this.publicInterface = {
                    updatePosition: function () {
                        return gadget.updatePosition.apply(gadget, arguments)
                    },
                    getLayoutManager: function () {
                        return gadget.getLayoutManager.apply(gadget, arguments)
                    },
                    setLayoutManager: function () {
                        return gadget.setLayoutManager.apply(gadget, arguments)
                    },
                    getElement: function () {
                        return gadget.$
                    },
                    move: function (targetUrl) {
                        return gadget.move(targetUrl)
                    },
                    remove: function () {
                        return gadget.remove.apply(gadget, arguments)
                    },
                    getId: function () {
                        return gadget.id
                    },
                    showShim: function () {
                        return gadget.showShim.apply(gadget, arguments)
                    },
                    hideShim: function () {
                        return gadget.hideShim.apply(gadget, arguments)
                    },
                    minimize: function () {
                        return gadget.minimize.apply(gadget, arguments)
                    },
                    maximize: function () {
                        return gadget.minimize.apply(gadget, arguments)
                    },
                    getSecurityToken: function () {
                        return gadget.securityToken
                    },
                    setSecurityToken: function (securityToken) {
                        gadget.securityToken = securityToken
                    }
                };
                if (this.isMaximizable) {
                    this.publicInterface.setView = function () {
                        return gadget.setView.apply(gadget, arguments)
                    }
                }
            }
            return this.publicInterface
        },
        init: function (options) {
            this.COOKIE_MINIMIZE = options.id + ":minimized";
            this.minimized = AG.Cookie.read(this.COOKIE_MINIMIZE) === "true";
            this.title = options.title;
            this.color = options.color;
            this.colorUrl = options.colorUrl;
            this.gadgetUrl = options.gadgetUrl;
            this.id = options.id;
            this.hasNonHiddenUserPrefs = options.hasNonHiddenUserPrefs;
            this.isMaximizable = options.isMaximizable;
            this.titleUrl = options.titleUrl;
            this.gadgetSpecUrl = options.gadgetSpecUrl;
            this.userPrefs = options.userPrefs;
            this.renderedGadgetUrl = options.renderedGadgetUrl;
            this.column = options.column;
            this.loaded = options.loaded;
            this.errorMessage = options.errorMessage;
            this.securityToken = AJS.parseUri(options.renderedGadgetUrl).queryKey["st"];
            this.draw(options)
        }
    };
    AG.Gadget = function (options) {
        var gadget = AJS.clone(Gadget);
        gadget.init(options);
        return gadget.getPublicInstance()
    };
    AG.Gadget.COLORS = [1, 2, 3, 4, 5, 6, 7, 8];
    AG.Gadget.getColorAttrName = function (color) {
        return "color" + color
    };
    AG.Gadget.isCanvasView = function (gadgetId) {
        var uri = AJS.parseUri(window.location.href);
        return new RegExp(gadgetId).test(uri.anchor)
    };
    AG.Gadget.getNullGadgetRepresentation = function (errorGadget) {
        return AJS.$.extend(errorGadget, {
            title: AG.param.get("errorGadgetTitle"),
            renderedGadgetUrl: AG.param.get("errorGadgetUrl"),
            color: errorGadget.color || "color7"
        })
    }
})();
AG.render = function () {
    var TEMPLATES_IFRAME_ID = "templates",
        parsers = {},
        setParser = function (template, parser) {
            parsers[template] = parser
        },
        getParser = function (template) {
            return parsers[template]
        },
        setContext = function () {
            AG.render.ctx = "body";
            if (AJS.debug) {
                if (AG.render.ctx.length === 0) {
                    console.error("AG.render: Rendering Failed! <iframe> storing templates is either not present OR has been" + "included AFTER the call to this method")
                }
            }
        },
        bindMacros = function (template, ignore) {
            var str = "",
                macros = [];
            ignore = ignore || [];
            var matches = template.match(/(?:\$[\W]*)(\w+)(?:\s*\([^\}]+})/gi);
            if (matches) {
                AJS.$.each(matches, function () {
                    var macroName = this.replace(/\$\{([\d\w]*).*/, "$1");
                    if (AJS.$.inArray(macroName, macros) === -1) {
                        if (AJS.$.inArray(macroName, ignore) === -1) {
                            macros.push(macroName);
                            ignore.push(macroName)
                        }
                    }
                })
            }
            AJS.$.each(macros, function () {
                var macro = AJS.$("#" + this, AG.render.ctx).html();
                str += bindMacros(macro, ignore);
                str += ["<?macro " + this + "(data)?>", macro, "<?/macro?>"].join("")
            });
            if (arguments.length === 1) {
                str += template
            }
            return str
        },
        render = function (descriptor) {
            var templateSrc, template = descriptor.useTemplate,
                parser = getParser(template);
            if (!parser) {
                parser = new ZParse(Implementation);
                templateSrc = AJS.$("#" + template);
                if (template.length > 0) {
                    parser.parse(bindMacros(templateSrc.html()));
                    setParser(template, parser)
                } else {
                    if (AJS.debug) {
                        console.error("AG.render: Rendering Failed! Template '" + template + "' does not exist.")
                    }
                }
            } else {
                if (AJS.debug) {
                    console.log("AG.render: Using cached parser")
                }
            }
            return parser.process(descriptor)
        };
    return function (descriptor, data) {
        if (typeof descriptor !== "object") {
            descriptor = AG.render.getDescriptor(descriptor, data)
        }
        if (!AG.render.ctx) {
            setContext()
        }
        return render(descriptor)
    }
}();
AG.render.ready = function (func) {
    AG.render.ready.callbacks.push(func)
};
AG.render.ready.callbacks = [];
AG.render.initialize = function () {
    AJS.$.each(AG.render.ready.callbacks, function () {
        this()
    })
};
AG.render.getDescriptor = function () {
    var descriptors = {
        layoutDialog: function (args) {
            return AJS.$.extend({
                closeId: "dialog-close"
            }, args)
        },
        gadget: function (args) {
            function generateMenuItems() {
                var menu = [];

                function isEditable() {
                    return !!(isWritable() && args.hasNonHiddenUserPrefs)
                }
                function isWritable() {
                    return args.layout.writable
                }
                function generateColorList() {
                    var colorList = [];
                    AJS.$.each(AG.Gadget.COLORS, function () {
                        var color = AG.Gadget.getColorAttrName(this);
                        colorList.push({
                            styleClass: color,
                            link: {
                                href: "#",
                                text: AG.param.get(color)
                            }
                        })
                    });
                    return {
                        styleClass: "item-link gadget-colors",
                        items: colorList
                    }
                }
                if (isEditable()) {
                    menu.push({
                        styleClass: "dropdown-item",
                        link: {
                            styleClass: "item-link edit",
                            href: "#gadget-" + args.id + "-edit",
                            text: AG.param.get("edit")
                        }
                    })
                }
                menu.push({
                    styleClass: "dropdown-item",
                    link: {
                        styleClass: "item-link " + (args.minimized ? "maximization" : "minimization"),
                        href: "#",
                        text: args.minimized ? AG.param.get("expand") : AG.param.get("minimize")
                    }
                });
                if (isWritable()) {
                    menu.push(generateColorList());
                    menu.push({
                        styleClass: "dropdown-item",
                        link: {
                            styleClass: "item-link delete",
                            href: "#",
                            text: AG.param.get("remove")
                        }
                    })
                }
                return menu
            }
            return AJS.$.extend({
                menu: {
                    trigger: {
                        text: "Gadget menu",
                        href: "#"
                    },
                    list: {
                        items: generateMenuItems()
                    }
                }
            }, args)
        },
        dashboardMenu: function (args) {
            return args
        }
    };
    return function (name, data) {
        var descriptor;
        if (AJS.$.isFunction(descriptors[name])) {
            descriptor = descriptors[name](data)
        } else {
            if (descriptors[name]) {
                descriptor = descriptors[name]
            } else {
                if (AJS.debug) {
                    console.error("AG.render.getDescriptor: Could not find descriptor '" + name + "'")
                }
            }
        }
        if (descriptor) {
            return AJS.$.extend(descriptor, {
                useTemplate: name
            })
        }
    }
}();
if (typeof AG === "undefined") {
    var AG = {}
}
if (!console.warn) {
    console.warn = function () {}
}
AG.param = (function () {
    var strs = {};
    return {
        get: function (key) {
            var args = arguments;
            if (strs[key]) {
                if (arguments.length > 1) {
                    args[0] = strs[key];
                    return AJS.format.apply(this, args)
                } else {
                    return strs[key]
                }
            } else {
                if (AJS.debug) {
                    console.warn("param.get: Key '" + key + "' does not exist.")
                }
                return null
            }
        },
        set: function (key, str) {
            var setParam = function () {
                    var k = arguments[0];
                    var v = arguments[1];
                    if (typeof k === "string") {
                        strs[k] = v
                    } else {
                        if (AJS.debug) {
                            console.warn("param.set: Ignored param.set, key may be undefined. " + "Printing value...");
                            console.log(k)
                        }
                    }
                };
            if (arguments.length === 1 && typeof arguments[0] === "object") {
                AJS.$.each(arguments[0], function (key, str) {
                    setParam(key, str)
                })
            } else {
                if (arguments.length === 2) {
                    setParam(arguments[0], arguments[1])
                } else {
                    if (AJS.debug) {
                        console.warn("param.set: Expected arguments to be of length 1 or 2, however recieved a length of " + arguments.length + ". Printing value...");
                        console.log(arguments)
                    }
                }
            }
        },
        clear: function () {
            if (AJS.debug) {
                strs = {}
            }
        }
    }
}());
(function () {
    var COOKIE_NAME = "AG.congolmerate.cookie";

    function getValueFromCongolmerate(name, cookieValue) {
        if (cookieValue == null) {
            cookieValue = ""
        }
        var eq = name + "=";
        var cookieParts = cookieValue.split("|");
        for (var i = 0; i < cookieParts.length; i++) {
            var cp = cookieParts[i];
            while (cp.charAt(0) == " ") {
                cp = cp.substring(1, cp.length)
            }
            if (cp.indexOf(name) == 0) {
                return cp.substring(eq.length, cp.length)
            }
        }
        return null
    }
    function addOrAppendToValue(name, value, cookieValue) {
        var newCookieValue = "";
        if (cookieValue == null) {
            cookieValue = ""
        }
        var cookieParts = cookieValue.split("|");
        for (var i = 0; i < cookieParts.length; i++) {
            var cp = cookieParts[i];
            if (cp != "") {
                while (cp.charAt(0) == " ") {
                    cp = cp.substring(1, cp.length)
                }
                if (cp.indexOf(name) != 0) {
                    newCookieValue += cp + "|"
                }
            }
        }
        if (value != null && value != "") {
            var pair = name + "=" + value;
            if ((newCookieValue.length + pair.length) < 4020) {
                newCookieValue += pair
            }
        }
        return newCookieValue
    }
    function getCookieValue(name) {
        var eq = name + "=",
            ca = document.cookie.split(";");
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == " ") {
                c = c.substring(1, c.length)
            }
            if (c.indexOf(eq) == 0) {
                return c.substring(eq.length, c.length)
            }
        }
        return null
    }
    function saveCookie(name, value, days) {
        var ex;
        if (days) {
            var d = new Date();
            d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
            ex = "; expires=" + d.toGMTString()
        } else {
            ex = ""
        }
        document.cookie = name + "=" + value + ex + ";path=/"
    }
    AG.Cookie = {
        save: function (name, value) {
            var cookieValue;
            if (window.localStorage) {
                cookieValue = localStorage.getItem(COOKIE_NAME)
            } else {
                cookieValue = getCookieValue(COOKIE_NAME)
            }
            cookieValue = addOrAppendToValue(name, value, cookieValue);
            if (window.localStorage) {
                localStorage.setItem(COOKIE_NAME, cookieValue)
            } else {
                saveCookie(COOKIE_NAME, cookieValue, 365)
            }
        },
        read: function (name, defaultValue) {
            var cookieValue, value;
            if (window.localStorage) {
                cookieValue = localStorage.getItem(COOKIE_NAME)
            } else {
                cookieValue = getCookieValue(COOKIE_NAME)
            }
            value = getValueFromCongolmerate(name, cookieValue);
            if (value != null) {
                return value
            }
            return defaultValue
        },
        erase: function (name) {
            this.save(name, "")
        }
    }
})();
AG.Sortable = function () {
    var sortableControl, dragGadget, hotspots = [],
        options = {
            cursor: "move",
            items: "li.gadget",
            tolerance: "pointer",
            placeholder: "placeholder",
            forcePointerForContainers: true,
            scroll: true,
            revert: AJS.$.browser.safari ? false : 250,
            scrollSensitivity: 300,
            scrollSpeed: 16,
            zIndex: 10,
            helper: function (event, item) {
                return item.get(0).getGadgetInstance().getElement()
            },
            change: function () {
                AG.DashboardManager.getLayout().refresh()
            },
            start: function (event, obj) {
                dragGadget = obj.item.get(0).getGadgetInstance();

                function preventTextSelection() {
                    if (typeof document.onselectstart !== "undefined") {
                        document.onselectstart = function () {
                            return false
                        }
                    }
                }
                function preventHelperRemovalOnDrop() {
                    obj.item.removeValidator = AJS.$.aop.around({
                        target: AJS.$,
                        method: "remove"
                    }, function (invocation) {
                        if (obj.helper !== this) {
                            invocation.proceed()
                        }
                    })
                }
                function setPlaceholder() {
                    obj.placeholder.height(obj.helper.outerHeight() - 2).html("<p>" + AG.param.get("dragYourGadgetHere") + "</p>")
                }
                obj.helper.addClass("dragging");
                preventTextSelection();
                preventHelperRemovalOnDrop();
                setPlaceholder();
                AG.DashboardManager.getLayout().refresh();
                AG.DashboardManager.getDashboard().addClass("dragging");
                AG.DashboardManager.showShims();
                AG.DashboardManager.markReadOnlyLayouts()
            },
            stop: function (event, obj) {
                var gadgetElement = dragGadget.getElement();

                function enableTextSelection() {
                    if (typeof document.onselectstart !== "undefined") {
                        document.onselectstart = null
                    }
                }
                gadgetElement.layoutRep.css({
                    display: ""
                });
                gadgetElement.css({
                    height: "auto"
                }).removeClass("dragging");
                gadgetElement.shadow.hide();
                if (!dragGadget.hasBeenDropped) {
                    AG.DashboardManager.getLayout().saveLayout()
                } else {
                    sortableControl.sortable("option", "revert", 250)
                }
                enableTextSelection();
                AG.DashboardManager.getDashboard().removeClass("dragging");
                AG.DashboardManager.hideShims();
                AG.DashboardManager.getLayout().refresh();
                AG.DashboardManager.unmarkReadOnlyLayouts()
            }
        };
    return {
        serialize: function () {
            var params = {};
            AJS.$.each(this.columns.filter(":visible"), function (i) {
                params[i] = [];
                AJS.$.each(AJS.$(this).sortable("toArray"), function () {
                    params[i].push(AJS.$("#" + this).get(0).getGadgetInstance().getId())
                })
            });
            return params
        },
        addHotSpot: function (elem, callback) {
            var offset = elem.offset(),
                dashboardOffset = AG.DashboardManager.getDashboard().offset();
            hotspots.push(AJS.$("<div class='hotspot-shim hidden' />").hover(function () {
                dragGadget.getElement().css({
                    opacity: 0.5
                });
                elem.addClass("hover")
            }, function () {
                dragGadget.getElement().css({
                    opacity: ""
                });
                elem.removeClass("hover")
            }).mouseup(function () {
                sortableControl.sortable("option", "revert", false);
                dragGadget.hasBeenDropped = true;
                callback(dragGadget)
            }).css({
                height: elem.outerHeight(),
                width: elem.outerWidth(),
                left: offset.left - dashboardOffset.left,
                top: offset.top - dashboardOffset.top
            }).appendTo(AG.DashboardManager.getDashboard()))
        },
        update: function () {
            AG.Sortable.init()
        },
        init: function () {
            if (sortableControl) {
                sortableControl.sortable("destroy")
            }
            this.columns = AJS.$(".draggable .column.sortable");
            if (this.columns.length > 0) {
                sortableControl = this.columns.sortable(AJS.$.extend(options, {
                    connectWith: this.columns
                }))
            }
        }
    }
}();
AJS.MacroBrowser = {
    clone: function (selector) {
        return AJS.$(selector).clone().removeAttr("id")
    }
};
AJS.toInit(function ($) {
    var GADGET_BROWSER_PAGE = 0,
        EXTERNAL_DIRECTORIES_PAGE = 2,
        ADD_EXTERNAL_DIRECTORY_PAGE = 3;
    AJS.activeColumn = 0;
    if (!AG.param.get("writable")) {
        return
    }
    var dashboardDirectoryResourceUrl = AG.param.get("dashboardDirectoryResourceUrl");
    var dashboardSubscribedGadgetFeedsUrl = AG.param.get("dashboardSubscribedGadgetFeedsUrl");
    var dashboardResourceUrl = AG.param.get("dashboardResourceUrl");
    var errorStatus = AG.param.get("defaultErrorMessage");
    var removeButtonText = AG.param.get("removeFromDirectory");
    var browserContentLoading = false;
    var browserContentLoaded = false;
    var localeLang = AJS.$(".locale-lang", "#i18n-settings").val();
    var localeCountry = AJS.$(".locale-country", "#i18n-settings").val();
    var addGadgetToDashboard = function (gadgetUrl, callbacks) {
            var reqParams = {
                type: "POST",
                url: dashboardResourceUrl + ".json?" + (localeLang ? "locale.lang=" + localeLang : "") + (localeCountry ? "&locale.country=" + localeCountry : ""),
                contentType: "application/json",
                dataType: "json",
                data: JSON.stringify({
                    url: gadgetUrl,
                    columnIndex: AJS.activeColumn
                }),
                processData: false
            };
            $.extend(reqParams, callbacks);
            $.ajax(reqParams)
        };
    var insertGadgetIntoLiveDashboard = function (data) {
            AG.Cookie.erase("gadget-" + data.id + "-fh");
            AG.DashboardManager.addGadget(data, AJS.activeColumn)
        };
    var callbacks = function (extraData, success, error) {
            return {
                success: function (data, textStatus) {
                    success(extraData, data, textStatus)
                },
                error: function (request, textStatus, errorThrown) {
                    error(extraData, request, textStatus, errorThrown)
                }
            }
        };
    var addingEntry = function (button) {
            var button = $(button);
            $(".macro-button-add").removeAttr("disabled");
            $(".macro-button-remove").removeAttr("disabled");
            button.val(AG.param.get("addItNow"));
            button.parents(".macro-list-item").removeAttr("style");
            button.blur()
        };
    var addGadgetToDashboardSuccess = function (button, data, textStatus) {
            insertGadgetIntoLiveDashboard(data);
            var button = $(button);
            button.parents(".macro-list-item").css("background-color", "#fffe83").animate({
                backgroundColor: "transparent"
            }, 2000, "linear", function () {
                addingEntry(button)
            })
        };
    var addGadgetToDashboardError = function (button, request, textStatus, errorThrown) {
            console.log("addItNowError = " + errorThrown);
            $(button).removeClass("macro-button-add").addClass("macro-button-add-broken");
            $(button).siblings(".macro-button-remove").removeClass("macro-button-remove").addClass("macro-button-remove-broken");
            $(button).parents(".macro-list-item").css("background-color", "#faa");
            $(".macro-button-add").removeAttr("disabled");
            $(".macro-button-remove").removeAttr("disabled");
            button.blur()
        };
    var removeGadgetFromDirectorySuccess = function (button, data, textStatus) {
            showError(AG.param.get("gadgetRemovedSuccess"));
            var button = $(button);
            button.parents(".macro-list-item").remove()
        };
    var removeGadgetFromDirectoryError = function (button, request, textStatus, errorThrown) {
            if (request.status == 403 || request.status == 401) {
                showError(AG.param.get("dashboardErrorDirectoryPermissions"))
            } else {
                showError(AG.param.get("dashboardErrorFailedToAddGadget"))
            }
            console.log("addItNowError = " + errorThrown);
            $(button).siblings(".macro-button-add").removeClass("macro-button-add").addClass("macro-button-add-broken");
            $(button).removeClass("macro-button-remove").addClass("macro-button-remove-broken");
            $(button).parents(".macro-list-item").css("background-color", "#faa");
            button.val(AG.param.get("removeFromDirectory"));
            button.blur()
        };
    var findGadgetsByUrl = function (urls) {
            if (!AJS.$.isArray(urls)) {
                urls = new Array(urls)
            }
            var gadgetSelector = $.map(urls, function (url) {
                return ".macro-hidden-uri[value=" + url + "]"
            }).join(",");
            return $(gadgetSelector).parents(".macro-list-item")
        };
    var addGadgetToDirectory = function () {
            if ($("#add-gadget-url").val() != "") {
                $("#add-gadget-submit").attr("disabled", "disabled").val(AG.param.get("adding"));
                var xhr = $.ajax({
                    type: "POST",
                    url: dashboardDirectoryResourceUrl,
                    data: JSON.stringify({
                        url: $("#add-gadget-url").val()
                    }),
                    contentType: "application/json",
                    processData: false,
                    success: function () {
                        var gadgetUrl = $("#add-gadget-url").val();
                        clearBrowser();
                        loadBrowser(false, function () {
                            scrollToGadget(findGadgetsByUrl(gadgetUrl));
                            $("#add-gadget-url").val("");
                            $("#add-gadget-submit").val(AG.param.get("addGadget")).removeAttr("disabled")
                        })
                    },
                    error: function (request, textStatus, errorThrown) {
                        if (request.status == 403 || request.status == 401) {
                            showError(AG.param.get("dashboardErrorDirectoryPermissions"))
                        } else {
                            var errorMsg = AG.param.get("dashboardErrorFailedToAddGadget");
                            if (request.responseText) {
                                errorMsg += "\n\n" + request.responseText
                            }
                            showError(errorMsg)
                        }
                        $("#add-gadget-url").select();
                        $("#add-gadget-submit").val(AG.param.get("addGadget")).removeAttr("disabled")
                    }
                });
                $(xhr).throbber({
                    target: $("#dir-throbber")
                })
            }
        };
    var resolveApplicationFeed = function (baseUri) {
            return (baseUri.charAt(baseUri.length - 1) == "/" ? baseUri : baseUri + "/") + "rest/gadgets/1.0/g/feed"
        };
    var highlightFeed = function (feedUrl) {
            highlight($("#gadget-feed-subscriptions li a[href=" + feedUrl + "]").parent())
        };
    var subscribeToGadgetFeed = function () {
            if ($("#add-gadget-feed-subscription-url").val() != "") {
                var originalButtonValue = $("#add-subscription-submit").val(),
                    newFeedUrl = resolveApplicationFeed($("#add-gadget-feed-subscription-url").val());
                $("#add-gadget-feed-subscription-url").attr("disabled", "disabled");
                $("#add-subscription-submit").attr("disabled", "disabled").val(AG.param.get("adding"));
                $("#add-subscription-throbber").addClass("loading");
                $.ajax({
                    type: "POST",
                    url: dashboardSubscribedGadgetFeedsUrl,
                    data: JSON.stringify({
                        url: newFeedUrl
                    }),
                    contentType: "application/json",
                    processData: false,
                    success: function (directory) {
                        clearBrowser();
                        loadBrowser(false, function () {
                            $("#add-gadget-feed-subscription-url").removeAttr("disabled").val("");
                            $("#add-subscription-submit").val(originalButtonValue).removeAttr("disabled");
                            $("#add-subscription-throbber").removeClass("loading");
                            displaySubscribedGadgetFeeds(function () {
                                highlightFeed(newFeedUrl)
                            })
                        })
                    },
                    error: function (request, textStatus, errorThrown) {
                        if (request.status == 403 || request.status == 401) {
                            showError(AG.param.get("dashboardErrorDirectoryPermissions"))
                        } else {
                            showError(AG.param.get("dashboardErrorFailedToAddGadgetSubscription"))
                        }
                        $("#add-subscription-throbber").removeClass("loading");
                        $("#add-gadget-feed-subscription-url").removeAttr("disabled").select();
                        $("#add-subscription-submit").val(originalButtonValue).removeAttr("disabled")
                    }
                })
            }
        };
    var removeSubscriptionToGadgetFeed = function (feedResource, success) {
            $.ajax({
                type: "DELETE",
                url: feedResource,
                success: success,
                error: function (request, textStatus, errorThrown) {
                    if (request.status == 403 || request.status == 401) {
                        showError(AG.param.get("dashboardErrorDirectoryPermissions"))
                    } else {
                        showError(AG.param.get("dashboardErrorFailedToRemoveGadgetSubscription"))
                    }
                }
            })
        };
    var displaySubscribedGadgetFeeds = function (onLoad) {
            $("#gadget-feed-subscriptions ul").empty();
            var xhr = $.ajax({
                type: "GET",
                url: dashboardSubscribedGadgetFeedsUrl,
                dataType: "json",
                processData: false,
                success: function (result) {
                    if (result.feeds) {
                        $("#gadget-subscriptions-header").html(AG.param.get("directoryGadgetFeedSubscriptionExplanation"));
                        $.each(result.feeds, function () {
                            var applicationRepresentation, deleteLink = $("<a></a>").attr("href", this.self.href).attr("title", AG.param.get("unsubscribeFromFeed")).addClass("remove").text(AG.param.get("unsubscribeFromFeed")).click(function (event) {
                                if (confirm(AG.param.get("confirmRemoveSubscriptionToGadgetFeed"))) {
                                    var element = $(this);
                                    var li = element.parent();
                                    removeSubscriptionToGadgetFeed(this.href, function () {
                                        element.remove();
                                        li.append(AJS.$('<div class="throbber loading"></div>'));
                                        clearBrowser();
                                        loadBrowser(false, function () {
                                            if (!li.siblings().length) {
                                                $("#gadget-subscriptions-header").html(AG.param.get("directoryGadgetFeedSubscriptionEmptyExplanation"))
                                            }
                                            li.remove()
                                        })
                                    })
                                }
                                return AJS.stopEvent(event)
                            });
                            if (!this.invalid) {
                                if (this.icon) {
                                    applicationRepresentation = $("<img/>").attr("src", this.icon).attr("width", "16").attr("height", "16").attr("alt", this.name).attr("title", this.name).addClass("app")
                                } else {
                                    applicationRepresentation = $("<span/>").addClass("app").text(this.name)
                                }
                                $("#gadget-feed-subscriptions ul").append($("<li></li>").append(applicationRepresentation).append($(" <a></a>").attr("href", this.feed.href).attr("title", this.feed.href).text(this.base ? AJS.format(AG.param.get("subscribedFeedDescription"), this.base) : this.title)).append(deleteLink))
                            } else {
                                $("#gadget-feed-subscriptions ul").append($("<li class='aui-message aui-message-error aui-override'/>").append(AJS.format(AG.param.get("dashboardErrorLoadingFeed"), '<a href="' + this.feed.href + '">' + this.feed.href + "</a>")).append(deleteLink))
                            }
                        });
                        if ($.isFunction(onLoad)) {
                            onLoad()
                        }
                    }
                },
                error: function (request, textStatus, errorThrown) {
                    if (request.status == 403 || request.status == 401) {
                        showError(AG.param.get("dashboardErrorDirectoryPermissions"))
                    } else {
                        showError(AG.param.get("dashboardErrorFailedToGetGadgetSubscriptions"))
                    }
                    AJS.MacroBrowser.dialog.gotoPage(GADGET_BROWSER_PAGE)
                }
            });
            AJS.MacroBrowser.dialog.gotoPage(EXTERNAL_DIRECTORIES_PAGE);
            $(xhr).throbber({
                target: $("#gadget-subscriptions-throbber"),
                isLatentThreshold: 200
            })
        };
    var removeGadgetFromDirectory = function (gadgetUri, callbacks) {
            var reqParams = {
                type: "DELETE",
                url: gadgetUri
            };
            $.extend(reqParams, callbacks);
            $.ajax(reqParams)
        };
    var scrollToGadget = function (gadget) {
            highlightGadget(gadget);
            var divOffset = $(".dialog-panel-body").offset().top;
            var pOffset = gadget.offset().top;
            var pScroll = pOffset - divOffset;
            $(".dialog-panel-body").animate({
                scrollTop: "+=" + pScroll + "px"
            }, 1000)
        };
    var highlightGadget = function (gadgets) {
            AJS.MacroBrowser.dialog.gotoPage(GADGET_BROWSER_PAGE);
            highlight(gadgets)
        };
    var highlight = function (element) {
            $(element).css("background-color", "#fffe83").animate({
                backgroundColor: "transparent"
            }, 5000, "linear", function () {
                $(this).css("background-color", "")
            })
        };
    var fillMacroTemplate = function (gadgetDiv, gadget) {
            var onAdd = function (event) {
                    if (AG.DashboardManager.getLayout().getGadgets().length >= AG.param.get("maxGadgets")) {
                        showError(AG.param.get("dashboardErrorTooManyGadgets"));
                        return false
                    }
                    var button = $(".macro-button-add", gadgetDiv);
                    button.attr("disabled", "disabled").val(AG.param.get("adding"));
                    $(".macro-button-add").attr("disabled", "disabled");
                    $(".macro-button-remove").attr("disabled", "disabled");
                    var gadgetUrl = button.siblings(".macro-hidden-uri").attr("value");
                    addGadgetToDashboard(gadgetUrl, callbacks(button, addGadgetToDashboardSuccess, addGadgetToDashboardError));
                    return false
                };
            if (gadget.thumbnailUri && gadget.thumbnailUri != "") {
                gadgetDiv.prepend("<img src='" + gadget.thumbnailUri + "' alt='' width='120' height='60'/>")
            }
            if (gadget.description && gadget.description != "") {
                $(".macro-desc", gadgetDiv).append(gadget.description).attr("title", gadget.description)
            } else {
                $(".macro-desc", gadgetDiv).append("<span class='unknown'>" + AG.param.get("descriptionNotAvailable") + "</span>")
            }
            if (gadget.authorName && gadget.authorName != "") {
                $(".macro-author", gadgetDiv).append(AJS.format(AG.param.get("gadgetAuthor"), "<a href='mailto:" + gadget.authorEmail + "'>" + gadget.authorName + "</a>"))
            } else {
                $(".macro-author", gadgetDiv).append("<span class='unknown'>" + AG.param.get("authorUnknown") + "</span>")
            }
            $(".macro-title", gadgetDiv).append("<a href=''>" + gadget.title + "</a>");
            $(".macro-title", gadgetDiv).click(onAdd);
            if (gadget.titleUri && gadget.titleUri != "") {
                $(".macro-title-uri-link", gadgetDiv).attr("href", gadget.titleUri)
            } else {
                $(".macro-title-uri", gadgetDiv).hide()
            }
            var gadgetUri = (gadget.gadgetSpecUri.match("^https?://") ? "" : AG.param.get("dashboardDirectoryBaseUrl")) + gadget.gadgetSpecUri;
            $(".macro-uri", gadgetDiv).attr("href", gadgetUri).attr("title", gadgetUri).text(gadgetUri);
            $(".macro-hidden-uri", gadgetDiv).val(gadget.gadgetSpecUri);
            $(".macro-button-add", gadgetDiv).click(onAdd);
            if (AG.param.get("canAddExternalGadgetsToDirectory") == "true") {
                if (gadget.isDeletable) {
                    $(".macro-button-remove", gadgetDiv).css("display", "block").click(function (event) {
                        if (confirm(AG.param.get("removeGadget"))) {
                            var button = $(this);
                            button.attr("disabled", "disabled").val(AG.param.get("removing"));
                            button.siblings(".macro-button-add").attr("disabled", "disabled");
                            var gadgetUrl = button.siblings(".macro-hidden-uri").attr("value");
                            removeGadgetFromDirectory(gadget.self, callbacks(button, removeGadgetFromDirectorySuccess, removeGadgetFromDirectoryError))
                        }
                        return false
                    })
                }
            }
        };
    var constructBrowser = function () {
            var mb = AJS.MacroBrowser.dialog = new AJS.Dialog(860, 530, "macro-browser-dialog");
            mb.addHeader(AG.param.get("gadgetDirectory"));
            if (AG.param.get("canAddExternalGadgetsToDirectory") == "true") {
                mb.addButton(AG.param.get("addByUrlButtonLabel"), function (dialog) {
                    dialog.nextPage();
                    $("#add-gadget-url").focus()
                }, "add-by-url left");
                mb.addButton(AG.param.get("subscribedGadgetFeedsButtonLabel"), function (dialog) {
                    displaySubscribedGadgetFeeds()
                }, "display-gadget-feed-subscriptions left")
            }
            if (!mb.page[0].buttonpanel) {
                mb.page[0].buttonpanel = AJS("div").addClass("dialog-button-panel");
                mb.page[0].element.append(mb.page[0].buttonpanel)
            }
            var helpLink = AJS("span").attr("class", "directory-help-link");
            AJS("a").html(AG.param.get("helpLinkLearnMoreAboutGadgets")).attr("href", AG.param.get("helpLinkLearnMoreAboutGadgetsUrl")).attr("target", "_blank").appendTo(helpLink);
            AJS("a").html(AG.param.get("helpLinkCreateYourOwnGadget")).attr("href", AG.param.get("helpLinkCreateYourOwnGadgetUrl")).attr("target", "_blank").appendTo(helpLink);
            mb.page[0].buttonpanel.append(helpLink);
            mb.addButton(AG.param.get("finishButtonLabel"), function (dialog) {
                dialog.hide()
            }, "finish");
            if (AG.param.get("canAddExternalGadgetsToDirectory") == "true") {
                mb.addPage().addPanel("addByUrl", $("#add-by-url-template")).addButton(AG.param.get("backButtonLabel"), function (dialog) {
                    dialog.prevPage()
                }, "back").addButton(AG.param.get("finishButtonLabel"), function (dialog) {
                    dialog.hide()
                }, "finish");
                mb.page[1].addHeader(AG.param.get("addGadgetByUrl"));
                $("#add-gadget-url").keydown(function (e) {
                    if (e.keyCode == 13) {
                        $("#add-gadget-submit").click()
                    }
                });
                $("#add-gadget-submit").click(function () {
                    addGadgetToDirectory()
                });
                mb.addPage().addPanel("gadgetFeedSubscriptions", $("#gadget-feed-subscriptions-template")).addButton(AG.param.get("addGadgetFeedSubscriptionButtonLabel"), function (dialog) {
                    dialog.gotoPage(ADD_EXTERNAL_DIRECTORY_PAGE);
                    $("#add-gadget-feed-subscription-url").focus()
                }, "add left").addButton(AG.param.get("backButtonLabel"), function (dialog) {
                    dialog.gotoPage(GADGET_BROWSER_PAGE)
                }, "back").addButton(AG.param.get("finishButtonLabel"), function (dialog) {
                    dialog.hide()
                }, "finish");
                mb.page[2].addHeader(AG.param.get("gadgetFeedSubscriptions"));
                mb.addPage().addPanel("addGadgetFeedSubscription", $("#add-gadget-feed-subscription-template")).addButton(AG.param.get("backButtonLabel"), function (dialog) {
                    dialog.gotoPage(EXTERNAL_DIRECTORIES_PAGE)
                }, "back").addButton(AG.param.get("finishButtonLabel"), function (dialog) {
                    dialog.hide()
                }, "finish");
                mb.page[3].addHeader(AG.param.get("addGadgetFeedSubscription"));
                $("#add-gadget-feed-subscription").keydown(function (e) {
                    if (e.keyCode == 13) {
                        $("#add-subscription-submit").click()
                    }
                });
                $("#add-subscription-submit").click(function () {
                    subscribeToGadgetFeed()
                })
            }
            mb.page[0].header.prepend(AJS.$('<div id="macro-browser-throbber" class="throbber"></div>'));
            var searchInput = AJS.$("<input type='search'/>").attr("id", "macro-browser-search").keyup(function (e) {
                var text = AJS.$(e.target).val();
                var macroSummaries = AJS.$("#macro-browser-dialog .dialog-panel-body .macro-list-item");
                if (text !== "") {
                    var lowerCaseText = text.toLocaleLowerCase();
                    macroSummaries.each(function () {
                        var $element = AJS.$(this);
                        if ($element.text().toLocaleLowerCase().indexOf(lowerCaseText) >= 0) {
                            $element.show()
                        } else {
                            $element.hide()
                        }
                    })
                } else {
                    resetSearchResults()
                }
            }).focus(function (e) {
                var searchInput = AJS.$(e.target);
                if (searchInput.hasClass("blank-search")) {
                    searchInput.removeClass("blank-search").val("")
                }
            }).blur(function (e) {
                var searchInput = AJS.$(e.target);
                if (searchInput.val() == "") {
                    searchInput.addClass("blank-search").val(AG.param.get("blankSearchText"))
                }
            }).blur();
            mb.page[0].header.prepend(searchInput)
        };
    var loadBrowserContent = function (data, after) {
            var mb = AJS.MacroBrowser.dialog;
            data.categories.sort(function (one, two) {
                return (one.name > two.name ? 1 : -1)
            });
            data.gadgets.sort(function (one, two) {
                return (one.title > two.title ? 1 : -1)
            });
            var makeCategoryList = function (id) {
                    return $("#macro-summaries-template").clone().attr("id", "category-" + id)
                };
            var getScrollbarWidth = function () {
                    var div = $('<div style="width:100px;height:50px;overflow:hidden;position:absolute;top:-1000px;left:-1000px;"><div style="height:200px;"></div></div>');
                    $("body").append(div);
                    var w1 = $("div", div).innerWidth();
                    div.css("overflow", "auto");
                    var w2 = $("div", div).innerWidth();
                    $(div).remove();
                    return (w1 - w2)
                };
            var scrollbarWidth = getScrollbarWidth();
            var makeGadgetSummary = function (gadget) {
                    var macroDiv = AJS.MacroBrowser.clone("#macro-summary-template");
                    fillMacroTemplate(macroDiv, gadget);
                    return macroDiv
                };
            var categoryDivs = {
                all: makeCategoryList("all")
            };
            $(data.gadgets).each(function (i, gadget) {
                var title = gadget.title.replace(/[^A-Za-z0-9_]/g, "");
                var macroDiv = makeGadgetSummary(gadget).attr("id", "macro-" + title);
                categoryDivs.all.append(macroDiv);
                $([gadget.categories]).each(function (i, catKey) {
                    if (catKey.constructor == Array) {
                        for (var j = 0; j < catKey.length; ++j) {
                            categoryDivs[catKey[j]] = categoryDivs[catKey[j]] || makeCategoryList(j);
                            categoryDivs[catKey[j]].append(makeGadgetSummary(gadget).attr("id", catKey[j] + "-macro-" + title))
                        }
                    } else {
                        categoryDivs[catKey] = categoryDivs[catKey] || makeCategoryList(j);
                        categoryDivs[catKey].append(makeGadgetSummary(gadget).attr("id", catKey + "-macro-" + title))
                    }
                })
            });
            mb.page[0].addPanel(AG.param.get("all") + " (" + categoryDivs["all"].children().length + ")", categoryDivs["all"]);
            $(data.categories).each(function () {
                if (categoryDivs[this.name]) {
                    mb.page[0].addPanel(this.name + " (" + categoryDivs[this.name].children().length + ")", categoryDivs[this.name], this.name)
                }
            });
            mb.page[0].gotoPanel(0, 0);
            $(mb.page).each(function () {
                this.recalcSize()
            });
            if ($.isFunction(after)) {
                after()
            }
            mb.ready = true
        };
    var loadBrowser = function (displayDialog, after) {
            browserContentLoading = true;
            $("#macro-browser-throbber").addClass("loading");
            var xhr = $.ajax({
                type: "GET",
                dataType: "json",
                global: "false",
                cache: false,
                url: dashboardDirectoryResourceUrl + ".json",
                success: function (data) {
                    browserContentLoading = false;
                    browserContentLoaded = true;
                    loadBrowserContent(data, after);
                    $("#macro-browser-throbber").removeClass("loading");
                    if (displayDialog) {
                        showDialog()
                    }
                },
                error: function (request, textStatus, errorThrown) {
                    browserContentLoading = false;
                    $("#macro-browser-throbber").removeClass("loading");
                    if (request.status == 403 || request.status == 401) {
                        showError(AG.param.get("dashboardErrorDashboardPermissions"))
                    } else {
                        showError(AG.param.get("failedToLoadError"))
                    }
                }
            });
            if (displayDialog) {
                $(xhr).throbber({
                    target: $("#dash-throbber")
                })
            }
            $(xhr).throbber({
                target: $("#dir-throbber")
            })
        };
    var clearBrowser = function () {
            var mb = AJS.MacroBrowser.dialog;
            $(mb.page[0].panel).each(function () {
                this.body.remove()
            });
            $(mb.page[0].panel).each(function () {
                this.remove()
            });
            mb.page[0].curtab = 0;
            browserContentLoaded = false
        };
    var resetSearchResults = function () {
            AJS.$("#macro-browser-dialog .dialog-panel-body .macro-list-item").show()
        };
    var showDialog = function () {
            var mb = AJS.MacroBrowser;
            if (mb.dialog && mb.dialog.ready) {
                $(document).keyup(function (e) {
                    if (e.keyCode == 27) {
                        mb.dialog.hide();
                        $(document).unbind("keyup", arguments.callee);
                        $("#macro-browser-search").val("");
                        return AJS.stopEvent(e)
                    }
                });
                if (mb.selectedMacro) {
                    AJS.log("selectedMacro: " + mb.selectedMacro.name);
                    replicateSelectMacro(mb.selectedMacro.name)
                } else {
                    mb.dialog.show();
                    mb.dialog.gotoPanel(0, 0);
                    AJS.$("#macro-browser-search").val("").focus();
                    resetSearchResults()
                }
            } else {
                showError(errorStatus)
            }
        };
    var showError = function (message) {
            alert(message)
        };
    constructBrowser();
    $(".add-gadget-link").live("click", function (e) {
        AJS.activeColumn = 0;
        if ($(this).attr("id").substring(11)) {
            AJS.activeColumn = $(this).attr("id").substring(11)
        }
        if (browserContentLoaded) {
            showDialog()
        } else {
            if (!browserContentLoading) {
                loadBrowser(true)
            }
        }
        return AJS.stopEvent(e)
    })
})(AJS.$);
jQuery.cookie = function (name, value, options) {
    if (typeof value != "undefined") {
        options = options || {};
        if (value === null) {
            value = "";
            options.expires = -1
        }
        var expires = "";
        if (options.expires && (typeof options.expires == "number" || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == "number") {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000))
            } else {
                date = options.expires
            }
            expires = "; expires=" + date.toUTCString()
        }
        var path = options.path ? "; path=" + (options.path) : "";
        var domain = options.domain ? "; domain=" + (options.domain) : "";
        var secure = options.secure ? "; secure" : "";
        document.cookie = [name, "=", encodeURIComponent(value), expires, path, domain, secure].join("")
    } else {
        var cookieValue = null;
        if (document.cookie && document.cookie != "") {
            var cookies = document.cookie.split(";");
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                if (cookie.substring(0, name.length + 1) == (name + "=")) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break
                }
            }
        }
        return cookieValue
    }
};